summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis')
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml4
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl332
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs328
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs78
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs72
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs60
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs351
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs68
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs201
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs287
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs58
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs131
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs86
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs583
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs298
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs230
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs54
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs7
39 files changed, 1939 insertions, 1559 deletions
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index fab16b80f..4eb94d5bc 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -15,6 +15,7 @@ rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
@@ -23,8 +24,7 @@ rustc_span = { path = "../rustc_span" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_lint = { path = "../rustc_lint" }
+rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_type_ir = { path = "../rustc_type_ir" }
rustc_feature = { path = "../rustc_feature" }
-thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 1d7965ff5..02d1dfcd1 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,73 +1,144 @@
-hir_analysis_unrecognized_atomic_operation =
- unrecognized atomic operation function: `{$op}`
- .label = unrecognized atomic operation
+hir_analysis_ambiguous_lifetime_bound =
+ ambiguous lifetime bound, explicit lifetime bound required
-hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
- intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
- .label = expected {$expected} {$descr} {$expected ->
- [one] parameter
- *[other] parameters
- }
+hir_analysis_assoc_type_binding_not_allowed =
+ associated type bindings are not allowed here
+ .label = associated type not allowed here
-hir_analysis_unrecognized_intrinsic_function =
- unrecognized intrinsic function: `{$name}`
- .label = unrecognized intrinsic
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+ .suggestion = use a fully qualified path with inferred lifetimes
-hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
- lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
- .label = lifetimes do not match {$item_kind} in trait
- .generics_label = lifetimes in impl do not match this {$item_kind} in trait
- .where_label = this `where` clause might not match the one in the trait
- .bounds_label = this bound might be missing in the impl
+hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
hir_analysis_async_trait_impl_should_be_async =
method `{$method_name}` should be async because the method from the trait is async
.trait_item_label = required because the trait method is async
+hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
+ .label = deref recursion limit reached
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+ cannot capture late-bound const parameter in a constant
+ .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+ cannot capture late-bound type parameter in a constant
+ .label = parameter defined here
+
+hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+
+hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
+ .label = `for<...>` is here
+
+hir_analysis_const_bound_for_non_const_trait =
+ ~const can only be applied to `#[const_trait]` traits
+
+hir_analysis_const_impl_for_non_const_trait =
+ const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
+ .suggestion = mark `{$trait_name}` as const
+ .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ .adding = adding a non-const method body in the future would be a breaking change
+
+hir_analysis_const_param_ty_impl_on_non_adt =
+ the trait `ConstParamTy` may not be implemented for this type
+ .label = type is not a structure or enumeration
+
+hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
+
+hir_analysis_copy_impl_on_non_adt =
+ the trait `Copy` cannot be implemented for this type
+ .label = type is not a structure or enumeration
+
+hir_analysis_copy_impl_on_type_with_dtor =
+ the trait `Copy` cannot be implemented for this type; the type has a destructor
+ .label = `Copy` not allowed on types with destructors
+
+hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
+
hir_analysis_drop_impl_on_wrong_item =
the `Drop` trait may only be implemented for local structs, enums, and unions
.label = must be a struct, enum, or union in the current crate
+hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported
+
+hir_analysis_empty_specialization = specialization impl does not specialize any associated items
+ .note = impl is a specialization of this impl
+
+hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
+ .label = overflowed on value after {$discr}
+ .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+
+hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
hir_analysis_field_already_declared =
field `{$field_name}` is already declared
.label = field already declared
.previous_decl_label = `{$field_name}` first declared here
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+hir_analysis_function_not_found_in_trait = function not found in this trait
-hir_analysis_ambiguous_lifetime_bound =
- ambiguous lifetime bound, explicit lifetime bound required
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+ .note = required by this annotation
-hir_analysis_assoc_type_binding_not_allowed =
- associated type bindings are not allowed here
- .label = associated type not allowed here
+hir_analysis_functions_names_duplicated = functions names are duplicated
+ .note = all `#[rustc_must_implement_one_of]` arguments must be unique
-hir_analysis_parenthesized_fn_trait_expansion =
- parenthesized trait syntax expands to `{$expanded_type}`
+hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+ .label = cannot specialize default item `{$ident}`
+ .ok_label = parent `impl` is here
+ .note = to specialize, `{$ident}` in the parent `impl` must be marked `default`
-hir_analysis_typeof_reserved_keyword_used =
- `typeof` is a reserved keyword but unimplemented
- .suggestion = consider replacing `typeof(...)` with an actual type
- .label = reserved keyword
+hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
+ .note = parent implementation is in crate `{$cname}`
-hir_analysis_value_of_associated_struct_already_specified =
- the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
- .label = re-bound here
- .previous_bound_label = `{$item_name}` bound here first
+hir_analysis_invalid_union_field =
+ field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+ .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
-hir_analysis_unconstrained_opaque_type = unconstrained opaque type
- .note = `{$name}` must be used in combination with a concrete type within the same {$what}
+hir_analysis_invalid_union_field_sugg =
+ wrap the field type in `ManuallyDrop<...>`
+
+hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
+ lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
+ .label = lifetimes do not match {$item_kind} in trait
+ .generics_label = lifetimes in impl do not match this {$item_kind} in trait
+ .where_label = this `where` clause might not match the one in the trait
+ .bounds_label = this bound might be missing in the impl
+
+hir_analysis_linkage_type =
+ invalid type for variable with `#[linkage]` attribute
+
+hir_analysis_main_function_async = `main` function is not allowed to be `async`
+ .label = `main` function is not allowed to be `async`
+
+hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
+ .label = `main` cannot have generic parameters
+
+hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
hir_analysis_manual_implementation =
manual implementations of `{$trait_name}` are experimental
.label = manual implementations of `{$trait_name}` are experimental
.help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
-hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}`
+ .label = missing one of `{$missing_items_msg}` in implementation
+ .note = required because of this annotation
-hir_analysis_trait_object_declared_with_no_traits =
- at least one trait is required for an object type
- .alias_span = this alias does not contain a trait
+hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization
+
+hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
+ .label = missing `{$missing_items_msg}` in implementation
+
+hir_analysis_missing_trait_item_label = `{$item}` from trait
+
+hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}`
+
+hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
+ .note = default implementation of `{$missing_item_name}` is unstable
+ .some_note = use of unstable library feature '{$feature}': {$r}
+ .none_note = use of unstable library feature '{$feature}'
hir_analysis_missing_type_params =
the type {$parameterCount ->
@@ -91,137 +162,132 @@ hir_analysis_missing_type_params =
} to {$parameters}
.note = because of the default `Self` reference, type parameters must be specified on object types
-hir_analysis_copy_impl_on_type_with_dtor =
- the trait `Copy` cannot be implemented for this type; the type has a destructor
- .label = `Copy` not allowed on types with destructors
-
hir_analysis_multiple_relaxed_default_bounds =
type parameter has more than one relaxed default bound, only one is supported
-hir_analysis_copy_impl_on_non_adt =
- the trait `Copy` cannot be implemented for this type
- .label = type is not a structure or enumeration
-
-hir_analysis_const_impl_for_non_const_trait =
- const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
- .suggestion = mark `{$trait_name}` as const
- .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
- .adding = adding a non-const method body in the future would be a breaking change
-
-hir_analysis_const_bound_for_non_const_trait =
- ~const can only be applied to `#[const_trait]` traits
-
-hir_analysis_self_in_impl_self =
- `Self` is not valid in the self type of an impl block
- .note = replace `Self` with a different type
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
-hir_analysis_linkage_type =
- invalid type for variable with `#[linkage]` attribute
+hir_analysis_must_implement_not_function = not a function
-hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
- .label = deref recursion limit reached
- .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
-hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
- .label = `main` cannot have a `where` clause
+hir_analysis_must_implement_not_function_span_note = required by this annotation
-hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
- .suggestion = remove this annotation
+hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
+hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
+ .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
-hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
- .label = `start` is not allowed to be `#[track_caller]`
+hir_analysis_parenthesized_fn_trait_expansion =
+ parenthesized trait syntax expands to `{$expanded_type}`
-hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
- .label = `start` is not allowed to have `#[target_feature]`
+hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
+ .suggestion = cast the value to `{$cast_ty}`
+ .help = cast the value to `{$cast_ty}`
-hir_analysis_start_not_async = `start` is not allowed to be `async`
- .label = `start` is not allowed to be `async`
+hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
+ .label = not allowed in type signatures
-hir_analysis_start_function_where = start function is not allowed to have a `where` clause
- .label = start function cannot have a `where` clause
+hir_analysis_return_type_notation_conflicting_bound =
+ ambiguous associated function `{$assoc_name}` for `{$ty_name}`
+ .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
-hir_analysis_start_function_parameters = start function is not allowed to have type parameters
- .label = start function cannot have type parameters
+hir_analysis_return_type_notation_equality_bound =
+ return type notation is not allowed to use type equality
-hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
+hir_analysis_return_type_notation_missing_method =
+ cannot find associated function `{$assoc_name}` for `{$ty_name}`
-hir_analysis_main_function_async = `main` function is not allowed to be `async`
- .label = `main` function is not allowed to be `async`
+hir_analysis_return_type_notation_on_non_rpitit =
+ return type notation used on function that is not `async` and does not return `impl Trait`
+ .note = function returns `{$ty}`, which is not compatible with associated type return bounds
+ .label = this function must be `async` or return `impl Trait`
-hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
- .label = `main` cannot have generic parameters
+hir_analysis_self_in_impl_self =
+ `Self` is not valid in the self type of an impl block
+ .note = replace `Self` with a different type
-hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
- .label = C-variadic function must have a compatible calling convention
+hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
+ .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
-hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
- cannot capture late-bound type parameter in a constant
- .label = parameter defined here
+hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
+ .help = add `#![feature(min_specialization)]` to the crate attributes to enable
-hir_analysis_cannot_capture_late_bound_const_in_anon_const =
- cannot capture late-bound const parameter in a constant
- .label = parameter defined here
+hir_analysis_start_function_parameters = start function is not allowed to have type parameters
+ .label = start function cannot have type parameters
-hir_analysis_variances_of = {$variances_of}
+hir_analysis_start_function_where = start function is not allowed to have a `where` clause
+ .label = start function cannot have a `where` clause
-hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
- .suggestion = cast the value to `{$cast_ty}`
- .help = cast the value to `{$cast_ty}`
+hir_analysis_start_not_async = `start` is not allowed to be `async`
+ .label = `start` is not allowed to be `async`
-hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
+ .label = `start` is not allowed to have `#[target_feature]`
-hir_analysis_invalid_union_field =
- field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
- .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
+ .label = `start` is not allowed to be `#[track_caller]`
-hir_analysis_invalid_union_field_sugg =
- wrap the field type in `ManuallyDrop<...>`
+hir_analysis_static_specialize = cannot specialize on `'static` lifetime
-hir_analysis_return_type_notation_on_non_rpitit =
- return type notation used on function that is not `async` and does not return `impl Trait`
- .note = function returns `{$ty}`, which is not compatible with associated type return bounds
- .label = this function must be `async` or return `impl Trait`
+hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
-hir_analysis_return_type_notation_equality_bound =
- return type notation is not allowed to use type equality
+hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
-hir_analysis_return_type_notation_missing_method =
- cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
+hir_analysis_too_large_static = extern static is too large for the current architecture
-hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
- .label = not allowed in type signatures
+hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
+ .suggestion = remove this annotation
-hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
- .suggestion = use a fully qualified path with inferred lifetimes
+hir_analysis_trait_object_declared_with_no_traits =
+ at least one trait is required for an object type
+ .alias_span = this alias does not contain a trait
-hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
+hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
+ .label = needs exactly one variant, but has {$number}
+ .many_label = too many variants in `{$path}`
+ .multi_label = variant here
-hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
- .label = overflowed on value after {$discr}
- .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
+ .label = needs at most one non-zero-sized field, but has {$field_count}
+ .labels = this field is non-zero-sized
-hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
- .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
+hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
+ .label = needs at most one non-zero-sized field, but has {$field_count}
+ .labels = this field is non-zero-sized
-hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+hir_analysis_typeof_reserved_keyword_used =
+ `typeof` is a reserved keyword but unimplemented
+ .suggestion = consider replacing `typeof(...)` with an actual type
+ .label = reserved keyword
-hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
+hir_analysis_unconstrained_opaque_type = unconstrained opaque type
+ .note = `{$name}` must be used in combination with a concrete type within the same {$what}
-hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
- .note = required by this annotation
+hir_analysis_unrecognized_atomic_operation =
+ unrecognized atomic operation function: `{$op}`
+ .label = unrecognized atomic operation
-hir_analysis_must_implement_not_function = not a function
+hir_analysis_unrecognized_intrinsic_function =
+ unrecognized intrinsic function: `{$name}`
+ .label = unrecognized intrinsic
-hir_analysis_must_implement_not_function_span_note = required by this annotation
+hir_analysis_value_of_associated_struct_already_specified =
+ the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
+ .label = re-bound here
+ .previous_bound_label = `{$item_name}` bound here first
-hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
+hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
+ .label = C-variadic function must have a compatible calling convention
-hir_analysis_function_not_found_in_trait = function not found in this trait
+hir_analysis_variances_of = {$variances_of}
-hir_analysis_functions_names_duplicated = functions names are duplicated
- .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
+ .label = `main` cannot have a `where` clause
-hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
- .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
+hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
+ intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
+ .label = expected {$expected} {$descr} {$expected ->
+ [one] parameter
+ *[other] parameters
+ }
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 113c3f08a..7b922f5d5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -243,13 +243,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
if let Some(span) = note_span {
- err.span_note(span, &note);
+ err.span_note(span, note);
} else {
- err.note(&note);
+ err.note(note);
}
}
if candidates.len() > limit {
- err.note(&format!("and {} others", candidates.len() - limit));
+ err.note(format!("and {} others", candidates.len() - limit));
}
}
@@ -303,7 +303,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"associated type `{name}` not found for `{self_ty}` in the current scope"
);
err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
- err.note(&format!(
+ err.note(format!(
"the associated type was found for\n{type_candidates}{additional_types}",
));
add_def_label(&mut err);
@@ -390,10 +390,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut err = tcx.sess.struct_span_err(
name.span,
- &format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
+ format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
);
if !bounds.is_empty() {
- err.note(&format!(
+ err.note(format!(
"the following trait bounds were not satisfied:\n{}",
bounds.join("\n")
));
@@ -409,7 +409,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if !tcx.sess.source_map().is_span_accessible(span) {
continue;
}
- err.span_label(span, &msg);
+ err.span_label(span, msg);
}
add_def_label(&mut err);
err.emit()
@@ -589,7 +589,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
if !suggestions.is_empty() {
err.multipart_suggestion(
- &format!("specify the associated type{}", pluralize!(types_count)),
+ format!("specify the associated type{}", pluralize!(types_count)),
suggestions,
Applicability::HasPlaceholders,
);
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 3b5c67de2..39d1d1f2d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -24,7 +24,7 @@ fn generic_arg_mismatch_err(
arg: &GenericArg<'_>,
param: &GenericParamDef,
possible_ordering_error: bool,
- help: Option<&str>,
+ help: Option<String>,
) -> ErrorGuaranteed {
let sess = tcx.sess;
let mut err = struct_span_err!(
@@ -112,7 +112,7 @@ fn generic_arg_mismatch_err(
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
{
if let Res::Def(DefKind::Fn { .. }, id) = path.res {
- err.help(&format!("`{}` is a function item, not a type", tcx.item_name(id)));
+ err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
err.help("function item types cannot be named directly");
}
}
@@ -130,7 +130,7 @@ fn generic_arg_mismatch_err(
} else {
(arg.descr(), param.kind.descr())
};
- err.note(&format!("{} arguments must be provided before {} arguments", first, last));
+ err.note(format!("{} arguments must be provided before {} arguments", first, last));
if let Some(help) = help {
err.help(help);
}
@@ -300,7 +300,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
arg,
param,
!args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
- Some(&format!(
+ Some(format!(
"reorder the arguments: {}: `<{}>`",
param_types_present
.into_iter()
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 8d1156c17..2c60a0624 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -19,7 +19,7 @@ use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
- MultiSpan,
+ MultiSpan, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -38,7 +38,6 @@ use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}
use rustc_middle::ty::{DynKind, ToPredicate};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::edition::Edition;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_target::spec::abi;
@@ -56,6 +55,9 @@ use std::slice;
#[derive(Debug)]
pub struct PathSeg(pub DefId, pub usize);
+#[derive(Copy, Clone, Debug)]
+pub struct OnlySelfBounds(pub bool);
+
pub trait AstConv<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx>;
@@ -447,14 +449,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
- ty::Const::from_opt_const_arg_anon_const(
- tcx,
- ty::WithOptConstParam {
- did: ct.value.def_id,
- const_param_did: Some(param.def_id),
- },
- )
- .into()
+ let did = ct.value.def_id;
+ tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
+ ty::Const::from_anon_const(tcx, did).into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx
@@ -466,7 +463,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.astconv.ct_infer(ty, Some(param), inf.span).into()
} else {
self.inferred_params.push(inf.span);
- tcx.const_error(ty).into()
+ tcx.const_error_misc(ty).into()
}
}
_ => unreachable!(),
@@ -520,7 +517,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.no_bound_vars()
.expect("const parameter types cannot be generic");
if let Err(guar) = ty.error_reported() {
- return tcx.const_error_with_guaranteed(ty, guar).into();
+ return tcx.const_error(ty, guar).into();
}
if !infer_args && has_default {
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -529,7 +526,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.astconv.ct_infer(ty, Some(param), self.span).into()
} else {
// We've already errored above about the mismatch.
- tcx.const_error(ty).into()
+ tcx.const_error_misc(ty).into()
}
}
}
@@ -667,6 +664,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span: Span,
binding_span: Option<Span>,
constness: ty::BoundConstness,
+ polarity: ty::ImplPolarity,
bounds: &mut Bounds<'tcx>,
speculative: bool,
trait_ref_span: Span,
@@ -675,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args: &GenericArgs<'_>,
infer_args: bool,
self_ty: Ty<'tcx>,
+ only_self_bounds: OnlySelfBounds,
) -> GenericArgCountResult {
let (substs, arg_count) = self.create_substs_for_ast_path(
trait_ref_span,
@@ -694,13 +693,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
let poly_trait_ref =
- ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
+ ty::Binder::bind_with_vars(ty::TraitRef::new(tcx, trait_def_id, substs), bound_vars);
debug!(?poly_trait_ref, ?assoc_bindings);
- bounds.push_trait_bound(tcx, poly_trait_ref, span, constness);
+ bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity);
let mut dup_bindings = FxHashMap::default();
for binding in &assoc_bindings {
+ // Don't register additional associated type bounds for negative bounds,
+ // since we should have emitten an error for them earlier, and they will
+ // not be well-formed!
+ if polarity == ty::ImplPolarity::Negative {
+ self.tcx()
+ .sess
+ .delay_span_bug(binding.span, "negative trait bounds should not have bindings");
+ continue;
+ }
+
// Specify type to assert that error was already reported in `Err` case.
let _: Result<_, ErrorGuaranteed> = self.add_predicates_for_ast_type_binding(
hir_id,
@@ -711,6 +720,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&mut dup_bindings,
binding_span.unwrap_or(binding.span),
constness,
+ only_self_bounds,
+ polarity,
);
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
}
@@ -743,9 +754,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref: &hir::TraitRef<'_>,
span: Span,
constness: ty::BoundConstness,
+ polarity: ty::ImplPolarity,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
speculative: bool,
+ only_self_bounds: OnlySelfBounds,
) -> GenericArgCountResult {
let hir_id = trait_ref.hir_ref_id;
let binding_span = None;
@@ -763,6 +776,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span,
binding_span,
constness,
+ polarity,
bounds,
speculative,
trait_ref_span,
@@ -771,6 +785,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args,
infer_args,
self_ty,
+ only_self_bounds,
)
}
@@ -782,6 +797,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args: &GenericArgs<'_>,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
+ only_self_bounds: OnlySelfBounds,
) {
let binding_span = Some(span);
let constness = ty::BoundConstness::NotConst;
@@ -796,6 +812,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
span,
binding_span,
constness,
+ ty::ImplPolarity::Positive,
bounds,
speculative,
trait_ref_span,
@@ -804,6 +821,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args,
infer_args,
self_ty,
+ only_self_bounds,
);
}
@@ -827,7 +845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(b) = trait_segment.args().bindings.first() {
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
}
- self.tcx().mk_trait_ref(trait_def_id, substs)
+ ty::TraitRef::new(self.tcx(), trait_def_id, substs)
}
#[instrument(level = "debug", skip(self, span))]
@@ -952,28 +970,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ast_bounds: I,
bounds: &mut Bounds<'tcx>,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+ only_self_bounds: OnlySelfBounds,
) {
for ast_bound in ast_bounds {
match ast_bound {
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
- let constness = match modifier {
- hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
- hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
+ let (constness, polarity) = match modifier {
+ hir::TraitBoundModifier::MaybeConst => {
+ (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive)
+ }
+ hir::TraitBoundModifier::None => {
+ (ty::BoundConstness::NotConst, ty::ImplPolarity::Positive)
+ }
+ hir::TraitBoundModifier::Negative => {
+ (ty::BoundConstness::NotConst, ty::ImplPolarity::Negative)
+ }
hir::TraitBoundModifier::Maybe => continue,
};
-
let _ = self.instantiate_poly_trait_ref(
&poly_trait_ref.trait_ref,
poly_trait_ref.span,
constness,
+ polarity,
param_ty,
bounds,
false,
+ only_self_bounds,
);
}
&hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
self.instantiate_lang_item_trait_ref(
- lang_item, span, hir_id, args, param_ty, bounds,
+ lang_item,
+ span,
+ hir_id,
+ args,
+ param_ty,
+ bounds,
+ only_self_bounds,
);
}
hir::GenericBound::Outlives(lifetime) => {
@@ -1011,13 +1044,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
+ only_self_bounds: OnlySelfBounds,
) -> Bounds<'tcx> {
- self.compute_bounds_inner(param_ty, ast_bounds)
+ let mut bounds = Bounds::default();
+ self.add_bounds(
+ param_ty,
+ ast_bounds.iter(),
+ &mut bounds,
+ ty::List::empty(),
+ only_self_bounds,
+ );
+ debug!(?bounds);
+
+ bounds
}
/// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
/// named `assoc_name` into ty::Bounds. Ignore the rest.
- pub(crate) fn compute_bounds_that_match_assoc_type(
+ pub(crate) fn compute_bounds_that_match_assoc_item(
&self,
param_ty: Ty<'tcx>,
ast_bounds: &[hir::GenericBound<'_>],
@@ -1028,23 +1072,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for ast_bound in ast_bounds {
if let Some(trait_ref) = ast_bound.trait_ref()
&& let Some(trait_did) = trait_ref.trait_def_id()
- && self.tcx().trait_may_define_assoc_type(trait_did, assoc_name)
+ && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
{
result.push(ast_bound.clone());
}
}
- self.compute_bounds_inner(param_ty, &result)
- }
-
- fn compute_bounds_inner(
- &self,
- param_ty: Ty<'tcx>,
- ast_bounds: &[hir::GenericBound<'_>],
- ) -> Bounds<'tcx> {
let mut bounds = Bounds::default();
-
- self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
+ self.add_bounds(
+ param_ty,
+ result.iter(),
+ &mut bounds,
+ ty::List::empty(),
+ OnlySelfBounds(true),
+ );
debug!(?bounds);
bounds
@@ -1067,6 +1108,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
dup_bindings: &mut FxHashMap<DefId, Span>,
path_span: Span,
constness: ty::BoundConstness,
+ only_self_bounds: OnlySelfBounds,
+ polarity: ty::ImplPolarity,
) -> Result<(), ErrorGuaranteed> {
// Given something like `U: SomeTrait<T = X>`, we want to produce a
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
@@ -1097,11 +1140,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) {
trait_ref
} else {
- return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
- span: binding.span,
- trait_name: tcx.item_name(trait_ref.def_id()),
- assoc_name: binding.item_name.name,
- }));
+ self.one_bound_for_assoc_method(
+ traits::supertraits(tcx, trait_ref),
+ trait_ref.print_only_trait_path(),
+ binding.item_name,
+ path_span,
+ )?
}
} else if self.trait_defines_associated_item_named(
trait_ref.def_id(),
@@ -1115,7 +1159,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// those that do.
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, trait_ref),
- trait_ref.print_only_trait_path(),
+ trait_ref.skip_binder().print_only_trait_name(),
binding.item_name,
path_span,
match binding.kind {
@@ -1147,9 +1191,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.sess
.struct_span_err(
binding.span,
- &format!("{} `{}` is private", assoc_item.kind, binding.item_name),
+ format!("{} `{}` is private", assoc_item.kind, binding.item_name),
)
- .span_label(binding.span, &format!("private {}", assoc_item.kind))
+ .span_label(binding.span, format!("private {}", assoc_item.kind))
.emit();
}
tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
@@ -1321,11 +1365,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let expected = tcx.def_descr(assoc_item_def_id);
let mut err = tcx.sess.struct_span_err(
binding.span,
- &format!("expected {expected} bound, found {got}"),
+ format!("expected {expected} bound, found {got}"),
);
err.span_note(
tcx.def_span(assoc_item_def_id),
- &format!("{expected} defined here"),
+ format!("{expected} defined here"),
);
if let hir::def::DefKind::AssocConst = def_kind
@@ -1342,7 +1386,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
term = match def_kind {
hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
hir::def::DefKind::AssocConst => tcx
- .const_error_with_guaranteed(
+ .const_error(
tcx.type_of(assoc_item_def_id)
.subst(tcx, projection_ty.skip_binder().substs),
reported,
@@ -1366,8 +1410,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
//
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder.
- let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
- self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
+ //
+ // NOTE: If `only_self_bounds` is true, do NOT expand this associated
+ // type bound into a trait predicate, since we only want to add predicates
+ // for the `Self` type.
+ if !only_self_bounds.0 {
+ let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
+ self.add_bounds(
+ param_ty,
+ ast_bounds.iter(),
+ bounds,
+ projection_ty.bound_vars(),
+ only_self_bounds,
+ );
+ }
}
}
Ok(())
@@ -1405,9 +1461,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&trait_bound.trait_ref,
trait_bound.span,
ty::BoundConstness::NotConst,
+ ty::ImplPolarity::Positive,
dummy_self,
&mut bounds,
false,
+ // FIXME: This should be `true`, but we don't really handle
+ // associated type bounds or type aliases in objects in a way
+ // that makes this meaningful, I think.
+ OnlySelfBounds(false),
) {
potential_assoc_types.extend(cur_potential_assoc_types);
}
@@ -1471,7 +1532,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"additional use",
);
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
- err.help(&format!(
+ err.help(format!(
"consider creating a new trait with all of these as supertraits and using that \
trait here instead: `trait NewTrait: {} {{}}`",
regular_traits
@@ -1781,7 +1842,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([], []) => {
err.span_suggestion_verbose(
span,
- &format!(
+ format!(
"if there were a type named `Type` that implements a trait named \
`Trait` with associated type `{name}`, you could use the \
fully-qualified path",
@@ -1793,7 +1854,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([], [trait_str]) => {
err.span_suggestion_verbose(
span,
- &format!(
+ format!(
"if there were a type named `Example` that implemented `{trait_str}`, \
you could use the fully-qualified path",
),
@@ -1804,7 +1865,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([], traits) => {
err.span_suggestions(
span,
- &format!(
+ format!(
"if there were a type named `Example` that implemented one of the \
traits with associated type `{name}`, you could use the \
fully-qualified path",
@@ -1819,7 +1880,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
([type_str], []) => {
err.span_suggestion_verbose(
span,
- &format!(
+ format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for `{type_str}`, you could use the fully-qualified path",
),
@@ -1830,7 +1891,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(types, []) => {
err.span_suggestions(
span,
- &format!(
+ format!(
"if there were a trait named `Example` with associated type `{name}` \
implemented for one of the types, you could use the fully-qualified \
path",
@@ -1885,7 +1946,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let param_name = tcx.hir().ty_param_name(ty_param_def_id);
self.one_bound_for_assoc_type(
|| {
- traits::transitive_bounds_that_define_assoc_type(
+ traits::transitive_bounds_that_define_assoc_item(
tcx,
predicates.iter().filter_map(|(p, _)| {
Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
@@ -1996,7 +2057,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
);
}
} else {
- err.note(&format!(
+ err.note(format!(
"associated type `{}` could derive from `{}`",
ty_param_name,
bound.print_only_trait_path(),
@@ -2004,7 +2065,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
if !where_bounds.is_empty() {
- err.help(&format!(
+ err.help(format!(
"consider introducing a new type parameter `T` and adding `where` constraints:\
\n where\n T: {},\n{}",
ty_param_name,
@@ -2020,6 +2081,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Ok(bound)
}
+ #[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)]
+ fn one_bound_for_assoc_method(
+ &self,
+ all_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+ ty_name: impl Display,
+ assoc_name: Ident,
+ span: Span,
+ ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
+ let mut matching_candidates = all_candidates.filter(|r| {
+ self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
+ });
+
+ let candidate = match matching_candidates.next() {
+ Some(candidate) => candidate,
+ None => {
+ return Err(self.tcx().sess.emit_err(
+ crate::errors::ReturnTypeNotationMissingMethod {
+ span,
+ ty_name: ty_name.to_string(),
+ assoc_name: assoc_name.name,
+ },
+ ));
+ }
+ };
+
+ if let Some(conflicting_candidate) = matching_candidates.next() {
+ return Err(self.tcx().sess.emit_err(
+ crate::errors::ReturnTypeNotationConflictingBound {
+ span,
+ ty_name: ty_name.to_string(),
+ assoc_name: assoc_name.name,
+ first_bound: candidate.print_only_trait_path(),
+ second_bound: conflicting_candidate.print_only_trait_path(),
+ },
+ ));
+ }
+
+ Ok(candidate)
+ }
+
// Create a type from a path to an associated type or to an enum variant.
// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
// and item_segment is the path segment for `D`. We return a type and a def for
@@ -2061,7 +2162,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.note("enum variants can't have type parameters");
let type_name = tcx.item_name(adt_def.did());
let msg = format!(
- "you might have meant to specity type parameters on enum \
+ "you might have meant to specify type parameters on enum \
`{type_name}`"
);
let Some(args) = assoc_segment.args else { return; };
@@ -2072,14 +2173,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// work for the `enum`, instead of just looking if it takes *any*.
err.span_suggestion_verbose(
args_span,
- &format!("{type_name} doesn't have generic parameters"),
+ format!("{type_name} doesn't have generic parameters"),
"",
Applicability::MachineApplicable,
);
return;
}
let Ok(snippet) = tcx.sess.source_map().span_to_snippet(args_span) else {
- err.note(&msg);
+ err.note(msg);
return;
};
let (qself_sugg_span, is_self) = if let hir::TyKind::Path(
@@ -2113,12 +2214,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
kw::SelfUpper == segment.ident.name,
),
_ => {
- err.note(&msg);
+ err.note(msg);
return;
}
}
} else {
- err.note(&msg);
+ err.note(msg);
return;
};
let suggestion = vec![
@@ -2133,7 +2234,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(args_span, String::new()),
];
err.multipart_suggestion_verbose(
- &msg,
+ msg,
suggestion,
Applicability::MaybeIncorrect,
);
@@ -2185,7 +2286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let reported = if variant_resolution.is_some() {
// Variant in type position
let msg = format!("expected type, found variant `{}`", assoc_ident);
- tcx.sess.span_err(span, &msg)
+ tcx.sess.span_err(span, msg)
} else if qself_ty.is_enum() {
let mut err = struct_span_err!(
tcx.sess,
@@ -2256,7 +2357,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Assume that if it's not matched, there must be a const defined with the same name
// but it was used in a type position.
let msg = format!("found associated const `{assoc_ident}` when type was expected");
- let guar = tcx.sess.struct_span_err(span, &msg).emit();
+ let guar = tcx.sess.struct_span_err(span, msg).emit();
return Err(guar);
};
@@ -2276,7 +2377,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
also,
tcx.def_kind_descr(kind, def_id)
);
- lint.span_note(tcx.def_span(def_id), &note_msg);
+ lint.span_note(tcx.def_span(def_id), note_msg);
};
could_refer_to(DefKind::Variant, variant_def_id, "");
@@ -2317,19 +2418,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return Ok(None);
}
+ //
+ // Select applicable inherent associated type candidates modulo regions.
+ //
+
// In contexts that have no inference context, just make a new one.
// We do need a local variable to store it, though.
let infcx_;
let infcx = match self.infcx() {
Some(infcx) => infcx,
None => {
- assert!(!self_ty.needs_infer());
+ assert!(!self_ty.has_infer());
infcx_ = tcx.infer_ctxt().ignoring_regions().build();
&infcx_
}
};
- let param_env = tcx.param_env(block.owner.to_def_id());
+ // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
+ // when inside of an ADT (#108491) or where clause.
+ let param_env = tcx.param_env(block.owner);
let cause = ObligationCause::misc(span, block.owner.def_id);
let mut fulfillment_errors = Vec::new();
@@ -2337,6 +2444,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let universe = infcx.create_next_universe();
// Regions are not considered during selection.
+ // FIXME(non_lifetime_binders): Here we are "truncating" or "flattening" the universes
+ // of type and const binders. Is that correct in the selection phase? See also #109505.
let self_ty = tcx.replace_escaping_bound_vars_uncached(
self_ty,
FnMutDelegate {
@@ -2352,41 +2461,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
candidates
.iter()
- .filter_map(|&(impl_, (assoc_item, def_scope))| {
+ .copied()
+ .filter(|&(impl_, _)| {
infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
- let impl_ty = tcx.type_of(impl_);
let impl_substs = infcx.fresh_item_substs(impl_);
- let impl_ty = impl_ty.subst(tcx, impl_substs);
+ let impl_ty = tcx.type_of(impl_).subst(tcx, impl_substs);
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
- // Check that the Self-types can be related.
- // FIXME(fmease): Should we use `eq` here?
- ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).ok()?;
+ // Check that the self types can be related.
+ // FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses
+ // `sup` for this situtation, too. What for? To constrain inference variables?
+ if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err()
+ {
+ return false;
+ }
// Check whether the impl imposes obligations we have to worry about.
- let impl_bounds = tcx.predicates_of(impl_);
- let impl_bounds = impl_bounds.instantiate(tcx, impl_substs);
-
+ let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_substs);
let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
-
let impl_obligations = traits::predicates_for_generics(
|_, _| cause.clone(),
param_env,
impl_bounds,
);
-
ocx.register_obligations(impl_obligations);
let mut errors = ocx.select_where_possible();
if !errors.is_empty() {
fulfillment_errors.append(&mut errors);
- return None;
+ return false;
}
- // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot.
- Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs)))
+ true
})
})
.collect()
@@ -2395,24 +2503,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if applicable_candidates.len() > 1 {
return Err(self.complain_about_ambiguous_inherent_assoc_type(
name,
- applicable_candidates.into_iter().map(|(candidate, ..)| candidate).collect(),
+ applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
span,
));
}
- if let Some((assoc_item, def_scope, impl_substs)) = applicable_candidates.pop() {
+ if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
self.check_assoc_ty(assoc_item, name, def_scope, block, span);
- // FIXME(inherent_associated_types): To fully *confirm* the *probed* candidate, we still
- // need to relate the Self-type with fresh item substs & register region obligations for
- // regionck to prove/disprove.
-
- let item_substs =
- self.create_substs_for_associated_item(span, assoc_item, segment, impl_substs);
+ // FIXME(fmease): Currently creating throwaway `parent_substs` to please
+ // `create_substs_for_associated_item`. Modify the latter instead (or sth. similar) to
+ // not require the parent substs logic.
+ let parent_substs = InternalSubsts::identity_for_item(tcx, impl_);
+ let substs =
+ self.create_substs_for_associated_item(span, assoc_item, segment, parent_substs);
+ let substs = tcx.mk_substs_from_iter(
+ std::iter::once(ty::GenericArg::from(self_ty))
+ .chain(substs.into_iter().skip(parent_substs.len())),
+ );
- // FIXME(fmease, #106722): Check if the bounds on the parameters of the
- // associated type hold, if any.
- let ty = tcx.type_of(assoc_item).subst(tcx, item_substs);
+ let ty = tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(assoc_item, substs));
return Ok(Some((ty, assoc_item)));
}
@@ -2473,9 +2583,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let msg = format!("{kind} `{name}` is private");
let def_span = tcx.def_span(item);
tcx.sess
- .struct_span_err_with_code(span, &msg, rustc_errors::error_code!(E0624))
- .span_label(span, &format!("private {kind}"))
- .span_label(def_span, &format!("{kind} defined here"))
+ .struct_span_err_with_code(span, msg, rustc_errors::error_code!(E0624))
+ .span_label(span, format!("private {kind}"))
+ .span_label(def_span, format!("{kind} defined here"))
.emit();
}
tcx.check_stability(item, Some(block), span, None);
@@ -2494,7 +2604,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let infcx = if let Some(infcx) = self.infcx() {
infcx
} else {
- assert!(!qself_ty.needs_infer());
+ assert!(!qself_ty.has_infer());
infcx_ = tcx.infer_ctxt().build();
&infcx_
};
@@ -2515,7 +2625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let trait_ref = tcx.impl_trait_ref(impl_def_id);
- trait_ref.map_or(false, |trait_ref| {
+ trait_ref.is_some_and(|trait_ref| {
let impl_ = trait_ref.subst(
tcx,
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
@@ -2923,7 +3033,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.prohibit_generics(path.segments.iter(), |err| {
if let Some(span) = tcx.def_ident_span(def_id) {
let name = tcx.item_name(def_id);
- err.span_note(span, &format!("type parameter `{name}` defined here"));
+ err.span_note(span, format!("type parameter `{name}` defined here"));
}
});
@@ -2984,7 +3094,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut span: MultiSpan = vec![t_sp].into();
span.push_span_label(
i_sp,
- &format!("`Self` is on type `{type_name}` in this `impl`"),
+ format!("`Self` is on type `{type_name}` in this `impl`"),
);
let mut postfix = "";
if generics == 0 {
@@ -2992,11 +3102,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
span.push_span_label(
t_sp,
- &format!("`Self` corresponds to this type{postfix}"),
+ format!("`Self` corresponds to this type{postfix}"),
);
- err.span_note(span, &msg);
+ err.span_note(span, msg);
} else {
- err.note(&msg);
+ err.note(msg);
}
for segment in path.segments {
if let Some(args) = segment.args && segment.ident.name == kw::SelfUpper {
@@ -3044,7 +3154,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// the anon const, which is empty. This is why the
// `AlwaysApplicable` impl needs a `T: ?Sized` bound for
// this to compile if we were to normalize here.
- if forbid_generic && ty.needs_subst() {
+ if forbid_generic && ty.has_param() {
let mut err = tcx.sess.struct_span_err(
path.span,
"generic `Self` types are currently not permitted in anonymous constants",
@@ -3087,7 +3197,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(args) = segment.args {
err.span_suggestion_verbose(
segment.ident.span.shrink_to_hi().to(args.span_ext),
- &format!("primitive type `{name}` doesn't have generic parameters"),
+ format!("primitive type `{name}` doesn't have generic parameters"),
"",
Applicability::MaybeIncorrect,
);
@@ -3378,7 +3488,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if !infer_replacements.is_empty() {
diag.multipart_suggestion(
- &format!(
+ format!(
"try replacing `_` with the type{} in the corresponding trait method signature",
rustc_errors::pluralize!(infer_replacements.len()),
),
@@ -3544,7 +3654,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
..
}) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id
{
- if !of_trait_ref.trait_def_id().map_or(false, |def_id| def_id.is_local()) {
+ if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
return;
}
let of_trait_span = of_trait_ref.path.span;
@@ -3583,7 +3693,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.source_map()
.span_to_prev_source(self_ty.span)
.ok()
- .map_or(false, |s| s.trim_end().ends_with('<'));
+ .is_some_and(|s| s.trim_end().ends_with('<'));
let is_global = poly_trait_ref.trait_ref.path.is_global();
@@ -3607,7 +3717,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
));
}
- if self_ty.span.edition() >= Edition::Edition2021 {
+ if self_ty.span.edition().rust_2021() {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
let mut diag =
@@ -3621,7 +3731,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
// check if the impl trait that we are considering is a impl of a local trait
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
- diag.emit();
+ diag.stash(self_ty.span, StashKey::TraitMissingMethod);
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
tcx.struct_span_lint_hir(
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index ba2d4319a..d6d1498d7 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -1,6 +1,5 @@
use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::NormalizeExt;
use crate::traits::{self, TraitEngine, TraitEngineExt};
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::TypeVisitableExt;
@@ -9,6 +8,7 @@ use rustc_session::Limit;
use rustc_span::def_id::LocalDefId;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::Span;
+use rustc_trait_selection::traits::StructurallyNormalizeExt;
#[derive(Copy, Clone, Debug)]
pub enum AutoderefKind {
@@ -66,14 +66,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
}
// Otherwise, deref if type is derefable:
- let (kind, new_ty) =
- if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
- (AutoderefKind::Builtin, mt.ty)
- } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
- (AutoderefKind::Overloaded, ty)
+ let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
+ self.state.cur_ty.builtin_deref(self.include_raw_pointers)
+ {
+ debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
+ // NOTE: we may still need to normalize the built-in deref in case
+ // we have some type like `&<Ty as Trait>::Assoc`, since users of
+ // autoderef expect this type to have been structurally normalized.
+ if self.infcx.tcx.trait_solver_next()
+ && let ty::Alias(ty::Projection, _) = ty.kind()
+ {
+ let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
+ self.state.obligations.extend(obligations);
+ (AutoderefKind::Builtin, normalized_ty)
} else {
- return None;
- };
+ (AutoderefKind::Builtin, ty)
+ }
+ } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
+ (AutoderefKind::Overloaded, ty)
+ } else {
+ return None;
+ };
if new_ty.references_error() {
return None;
@@ -119,14 +132,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
debug!("overloaded_deref_ty({:?})", ty);
-
let tcx = self.infcx.tcx;
// <ty as Deref>
- let trait_ref = tcx.mk_trait_ref(tcx.lang_items().deref_trait()?, [ty]);
-
+ let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
let cause = traits::ObligationCause::misc(self.span, self.body_id);
-
let obligation = traits::Obligation::new(
tcx,
cause.clone(),
@@ -138,26 +148,48 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
return None;
}
- let normalized_ty = self
+ let (normalized_ty, obligations) =
+ self.structurally_normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, [ty]))?;
+ debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
+ self.state.obligations.extend(obligations);
+
+ Some(self.infcx.resolve_vars_if_possible(normalized_ty))
+ }
+
+ #[instrument(level = "debug", skip(self), ret)]
+ pub fn structurally_normalize(
+ &self,
+ ty: Ty<'tcx>,
+ ) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
+ let tcx = self.infcx.tcx;
+ let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
+
+ let cause = traits::ObligationCause::misc(self.span, self.body_id);
+ let normalized_ty = match self
.infcx
.at(&cause, self.param_env)
- .normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
- let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
- let normalized_ty =
- normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
- let errors = fulfillcx.select_where_possible(&self.infcx);
+ .structurally_normalize(ty, &mut *fulfill_cx)
+ {
+ Ok(normalized_ty) => normalized_ty,
+ Err(errors) => {
+ // This shouldn't happen, except for evaluate/fulfill mismatches,
+ // but that's not a reason for an ICE (`predicate_may_hold` is conservative
+ // by design).
+ debug!(?errors, "encountered errors while fulfilling");
+ return None;
+ }
+ };
+
+ let errors = fulfill_cx.select_where_possible(&self.infcx);
if !errors.is_empty() {
// This shouldn't happen, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
- debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
+ debug!(?errors, "encountered errors while fulfilling");
return None;
}
- let obligations = fulfillcx.pending_obligations();
- debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
- self.state.obligations.extend(obligations);
- Some(self.infcx.resolve_vars_if_possible(normalized_ty))
+ Some((normalized_ty, fulfill_cx.pending_obligations()))
}
/// Returns the final type we ended up with, which may be an inference
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 284b099e7..686066abb 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -42,8 +42,14 @@ impl<'tcx> Bounds<'tcx> {
trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
constness: ty::BoundConstness,
+ polarity: ty::ImplPolarity,
) {
- self.predicates.push((trait_ref.with_constness(constness).to_predicate(tcx), span));
+ self.predicates.push((
+ trait_ref
+ .map_bound(|trait_ref| ty::TraitPredicate { trait_ref, constness, polarity })
+ .to_predicate(tcx),
+ span,
+ ));
}
pub fn push_projection_bound(
@@ -57,7 +63,7 @@ impl<'tcx> Bounds<'tcx> {
pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
- let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty]));
+ let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span));
}
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0bb98fdf2..3b2c052e8 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -13,11 +13,12 @@ use rustc_hir::intravisit::Visitor;
use rustc_hir::{ItemKind, Node, PathSegment};
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
+use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
-use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
+use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::stability::EvalResult;
+use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -31,6 +32,7 @@ use rustc_target::abi::FieldIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _};
use std::ops::ControlFlow;
@@ -170,14 +172,12 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
if matches!(tcx.def_kind(def_id), DefKind::Static(_)
if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
{
- tcx.sess
- .struct_span_err(span, "extern static is too large for the current architecture")
- .emit();
+ tcx.sess.emit_err(errors::TooLargeStatic { span });
return;
}
// Generic statics are rejected, but we still reach this case.
Err(e) => {
- tcx.sess.delay_span_bug(span, &e.to_string());
+ tcx.sess.delay_span_bug(span, e.to_string());
return;
}
};
@@ -224,7 +224,7 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
return;
}
- check_opaque_meets_bounds(tcx, item.owner_id.def_id, substs, span, &origin);
+ check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin);
}
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
@@ -320,7 +320,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
};
let prohibit_opaque = tcx
.explicit_item_bounds(def_id)
- .iter()
+ .subst_identity_iter_copied()
.try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
if let Some(ty) = prohibit_opaque.break_value() {
@@ -336,7 +336,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
&tcx.sess.parse_sess,
sym::impl_trait_projections,
span,
- &format!(
+ format!(
"`{}` return type cannot contain a projection or `Self` that references \
lifetimes from a parent scope",
if is_async { "async fn" } else { "impl Trait" },
@@ -393,13 +393,12 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
fn check_opaque_meets_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
- substs: SubstsRef<'tcx>,
span: Span,
origin: &hir::OpaqueTyOrigin,
) {
let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
- hir::OpaqueTyOrigin::TyAlias => def_id,
+ hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
};
let param_env = tcx.param_env(defining_use_anchor);
@@ -408,6 +407,8 @@ fn check_opaque_meets_bounds<'tcx>(
.with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor))
.build();
let ocx = ObligationCtxt::new(&infcx);
+
+ let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
// `ReErased` regions appear in the "parent_substs" of closures/generators.
@@ -430,7 +431,7 @@ fn check_opaque_meets_bounds<'tcx>(
let ty_err = ty_err.to_string(tcx);
tcx.sess.delay_span_bug(
span,
- &format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
+ format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
);
}
}
@@ -450,9 +451,18 @@ fn check_opaque_meets_bounds<'tcx>(
match origin {
// Checked when type checking the function containing them.
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
+ // Nested opaque types occur only in associated types:
+ // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
+ // They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
+ // We don't have to check them here because their well-formedness follows from the WF of
+ // the projection input types in the defining- and use-sites.
+ hir::OpaqueTyOrigin::TyAlias { .. }
+ if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
// Can have different predicates to their defining use
- hir::OpaqueTyOrigin::TyAlias => {
- let outlives_env = OutlivesEnvironment::new(param_env);
+ hir::OpaqueTyOrigin::TyAlias { .. } => {
+ let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
+ let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
}
}
@@ -494,7 +504,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
debug!(
"check_item_type(it.def_id={:?}, it.name={})",
id.owner_id,
- tcx.def_path_str(id.owner_id.to_def_id())
+ tcx.def_path_str(id.owner_id)
);
let _indenter = indenter();
match tcx.def_kind(id.owner_id) {
@@ -538,7 +548,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
tcx,
assoc_item,
assoc_item,
- tcx.mk_trait_ref(id.owner_id.to_def_id(), trait_substs),
+ ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_substs),
);
}
_ => {}
@@ -620,11 +630,11 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
E0044,
"foreign items may not have {kinds} parameters",
)
- .span_label(item.span, &format!("can't have {kinds} parameters"))
+ .span_label(item.span, format!("can't have {kinds} parameters"))
.help(
// FIXME: once we start storing spans for type arguments, turn this
// into a suggestion.
- &format!(
+ format!(
"replace the {} parameters with concrete {}{}",
kinds,
kinds_pl,
@@ -791,16 +801,15 @@ fn check_impl_items_against_trait<'tcx>(
let is_implemented = leaf_def
.as_ref()
- .map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
+ .is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
missing_items.push(tcx.associated_item(trait_item_id));
}
// true if this item is specifically implemented in this impl
- let is_implemented_here = leaf_def
- .as_ref()
- .map_or(false, |node_item| !node_item.defining_node.is_from_trait());
+ let is_implemented_here =
+ leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait());
if !is_implemented_here {
let full_impl_span =
@@ -863,7 +872,7 @@ fn check_impl_items_against_trait<'tcx>(
if !missing_items.is_empty() {
let full_impl_span =
tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
- missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
+ missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
}
if let Some(missing_items) = must_implement_one_of {
@@ -987,10 +996,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
err.span_note(
tcx.def_span(def_spans[0].0),
- &format!(
- "`{}` has a `#[repr(align)]` attribute",
- tcx.item_name(def_spans[0].0)
- ),
+ format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
);
if def_spans.len() > 2 {
@@ -999,7 +1005,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
let ident = tcx.item_name(*adt_def);
err.span_note(
*span,
- &if first {
+ if first {
format!(
"`{}` contains a field of type `{}`",
tcx.type_of(def.did()).subst_identity(),
@@ -1076,8 +1082,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
let layout = tcx.layout_of(param_env.and(ty));
// We are currently checking the type this field came from, so it must be local
let span = tcx.hir().span_if_local(field.did).unwrap();
- let zst = layout.map_or(false, |layout| layout.is_zst());
- let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1);
+ let zst = layout.is_ok_and(|layout| layout.is_zst());
+ let align1 = layout.is_ok_and(|layout| layout.align.abi.bytes() == 1);
if !zst {
return (span, zst, align1, None);
}
@@ -1468,10 +1474,10 @@ fn opaque_type_cycle_error(
let ty_span = tcx.def_span(def_id);
if !seen.contains(&ty_span) {
let descr = if ty.is_impl_trait() { "opaque " } else { "" };
- err.span_label(ty_span, &format!("returning this {descr}type `{ty}`"));
+ err.span_label(ty_span, format!("returning this {descr}type `{ty}`"));
seen.insert(ty_span);
}
- err.span_label(sp, &format!("returning here with type `{ty}`"));
+ err.span_label(sp, format!("returning here with type `{ty}`"));
}
for closure_def_id in visitor.closures {
@@ -1508,8 +1514,8 @@ fn opaque_type_cycle_error(
}
if tcx.sess.opts.unstable_opts.drop_tracking_mir
&& let DefKind::Generator = tcx.def_kind(closure_def_id)
+ && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id)
{
- let generator_layout = tcx.mir_generator_witnesses(closure_def_id);
for interior_ty in &generator_layout.field_tys {
label_match(interior_ty.ty, interior_ty.source_info.span);
}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 5d119a773..8bf1e0e84 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -60,19 +60,21 @@ pub(super) fn compare_impl_method<'tcx>(
};
}
-/// This function is best explained by example. Consider a trait:
+/// This function is best explained by example. Consider a trait with it's implementation:
///
-/// trait Trait<'t, T> {
-/// // `trait_m`
-/// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
-/// }
+/// ```rust
+/// trait Trait<'t, T> {
+/// // `trait_m`
+/// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
+/// }
///
-/// And an impl:
+/// struct Foo;
///
-/// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
-/// // `impl_m`
-/// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
-/// }
+/// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+/// // `impl_m`
+/// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo { Foo }
+/// }
+/// ```
///
/// We wish to decide if those two method types are compatible.
/// For this we have to show that, assuming the bounds of the impl hold, the
@@ -82,7 +84,9 @@ pub(super) fn compare_impl_method<'tcx>(
/// type parameters to impl type parameters. This is taken from the
/// impl trait reference:
///
-/// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+/// ```rust,ignore (pseudo-Rust)
+/// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+/// ```
///
/// We create a mapping `dummy_substs` that maps from the impl type
/// parameters to fresh types and regions. For type parameters,
@@ -91,13 +95,17 @@ pub(super) fn compare_impl_method<'tcx>(
/// regions (Note: but only early-bound regions, i.e., those
/// declared on the impl or used in type parameter bounds).
///
-/// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+/// ```rust,ignore (pseudo-Rust)
+/// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+/// ```
///
/// Now we can apply `placeholder_substs` to the type of the impl method
/// to yield a new function type in terms of our fresh, placeholder
/// types:
///
-/// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+/// ```rust,ignore (pseudo-Rust)
+/// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+/// ```
///
/// We now want to extract and substitute the type of the *trait*
/// method and compare it. To do so, we must create a compound
@@ -106,11 +114,15 @@ pub(super) fn compare_impl_method<'tcx>(
/// type parameters. We extend the mapping to also include
/// the method parameters.
///
-/// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+/// ```rust,ignore (pseudo-Rust)
+/// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+/// ```
///
/// Applying this to the trait method type yields:
///
-/// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+/// ```rust,ignore (pseudo-Rust)
+/// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+/// ```
///
/// This type is also the same but the name of the bound region (`'a`
/// vs `'b`). However, the normal subtyping rules on fn types handle
@@ -579,7 +591,7 @@ fn compare_asyncness<'tcx>(
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m_def_id: LocalDefId,
-) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
+) -> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed> {
let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
let impl_trait_ref =
@@ -782,14 +794,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
})
});
debug!(%ty);
- collected_tys.insert(def_id, ty);
+ collected_tys.insert(def_id, ty::EarlyBinder(ty));
}
Err(err) => {
let reported = tcx.sess.delay_span_bug(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
- collected_tys.insert(def_id, tcx.ty_error(reported));
+ collected_tys.insert(def_id, ty::EarlyBinder(tcx.ty_error(reported)));
}
}
}
@@ -839,7 +851,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
});
self.types.insert(proj.def_id, (infer_ty, proj.substs));
// Recurse into bounds
- for (pred, pred_span) in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
+ for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
&ObligationCause::misc(self.span, self.body_id),
@@ -1163,7 +1175,7 @@ fn compare_self_type<'tcx>(
/// as the number of generics on the respective assoc item in the trait definition.
///
/// For example this code emits the errors in the following code:
-/// ```
+/// ```rust,compile_fail
/// trait Trait {
/// fn foo();
/// type Assoc<T>;
@@ -1273,7 +1285,7 @@ fn compare_number_of_generics<'tcx>(
let mut err = tcx.sess.struct_span_err_with_code(
spans,
- &format!(
+ format!(
"{} `{}` has {} {kind} parameter{} but its trait \
declaration has {} {kind} parameter{}",
item_kind,
@@ -1317,7 +1329,7 @@ fn compare_number_of_generics<'tcx>(
impl_count,
kind,
pluralize!(impl_count),
- suffix.unwrap_or_else(String::new),
+ suffix.unwrap_or_default(),
),
);
}
@@ -1547,7 +1559,7 @@ fn compare_synthetic_generics<'tcx>(
/// the same kind as the respective generic parameter in the trait def.
///
/// For example all 4 errors in the following code are emitted here:
-/// ```
+/// ```rust,ignore (pseudo-Rust)
/// trait Foo {
/// fn foo<const N: u8>();
/// type bar<const N: u8>;
@@ -2023,7 +2035,7 @@ pub(super) fn check_type_bounds<'tcx>(
};
let obligations: Vec<_> = tcx
- .bound_explicit_item_bounds(trait_ty.def_id)
+ .explicit_item_bounds(trait_ty.def_id)
.subst_iter_copied(tcx, rebased_substs)
.map(|(concrete_ty_bound, span)| {
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 111bf5e54..e0ba255cc 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -1,13 +1,17 @@
// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
//
// We don't do any drop checking during hir typeck.
-use crate::hir::def_id::{DefId, LocalDefId};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, ErrorGuaranteed};
-use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::util::IgnoreRegions;
-use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
+use rustc_middle::ty::util::CheckRegions;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_trait_selection::traits::{self, ObligationCtxt};
+
+use crate::errors;
+use crate::hir::def_id::{DefId, LocalDefId};
/// This function confirms that the `Drop` implementation identified by
/// `drop_impl_did` is not any more specialized than the type it is
@@ -27,22 +31,34 @@ use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
+ match tcx.impl_polarity(drop_impl_did) {
+ ty::ImplPolarity::Positive => {}
+ ty::ImplPolarity::Negative => {
+ return Err(tcx.sess.emit_err(errors::DropImplPolarity::Negative {
+ span: tcx.def_span(drop_impl_did),
+ }));
+ }
+ ty::ImplPolarity::Reservation => {
+ return Err(tcx.sess.emit_err(errors::DropImplPolarity::Reservation {
+ span: tcx.def_span(drop_impl_did),
+ }));
+ }
+ }
let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
- let dtor_predicates = tcx.predicates_of(drop_impl_did);
match dtor_self_type.kind() {
- ty::Adt(adt_def, self_to_impl_substs) => {
+ ty::Adt(adt_def, adt_to_impl_substs) => {
ensure_drop_params_and_item_params_correspond(
tcx,
drop_impl_did.expect_local(),
adt_def.did(),
- self_to_impl_substs,
+ adt_to_impl_substs,
)?;
ensure_drop_predicates_are_implied_by_item_defn(
tcx,
- dtor_predicates,
+ drop_impl_did.expect_local(),
adt_def.did().expect_local(),
- self_to_impl_substs,
+ adt_to_impl_substs,
)
}
_ => {
@@ -52,7 +68,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro
let span = tcx.def_span(drop_impl_did);
let reported = tcx.sess.delay_span_bug(
span,
- &format!("should have been rejected by coherence check: {dtor_self_type}"),
+ format!("should have been rejected by coherence check: {dtor_self_type}"),
);
Err(reported)
}
@@ -63,9 +79,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_did: LocalDefId,
self_type_did: DefId,
- drop_impl_substs: SubstsRef<'tcx>,
+ adt_to_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
- let Err(arg) = tcx.uses_unique_generic_params(drop_impl_substs, IgnoreRegions::No) else {
+ let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
return Ok(())
};
@@ -76,15 +92,15 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
struct_span_err!(tcx.sess, drop_impl_span, E0366, "`Drop` impls cannot be specialized");
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
- err.note(&format!("`{arg}` is mentioned multiple times"))
+ err.note(format!("`{arg}` is mentioned multiple times"))
}
ty::util::NotUniqueParam::NotParam(arg) => {
- err.note(&format!("`{arg}` is not a generic parameter"))
+ err.note(format!("`{arg}` is not a generic parameter"))
}
};
err.span_note(
item_span,
- &format!(
+ format!(
"use the same sequence of generic lifetime, type and const parameters \
as the {self_descr} definition",
),
@@ -96,237 +112,94 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
/// implied by assuming the predicates attached to self_type_did.
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx: TyCtxt<'tcx>,
- dtor_predicates: ty::GenericPredicates<'tcx>,
- self_type_did: LocalDefId,
- self_to_impl_substs: SubstsRef<'tcx>,
+ drop_impl_def_id: LocalDefId,
+ adt_def_id: LocalDefId,
+ adt_to_impl_substs: SubstsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
- let mut result = Ok(());
-
- // Here is an example, analogous to that from
- // `compare_impl_method`.
- //
- // Consider a struct type:
- //
- // struct Type<'c, 'b:'c, 'a> {
- // x: &'a Contents // (contents are irrelevant;
- // y: &'c Cell<&'b Contents>, // only the bounds matter for our purposes.)
- // }
- //
- // and a Drop impl:
- //
- // impl<'z, 'y:'z, 'x:'y> Drop for P<'z, 'y, 'x> {
- // fn drop(&mut self) { self.y.set(self.x); } // (only legal if 'x: 'y)
- // }
- //
- // We start out with self_to_impl_substs, that maps the generic
- // parameters of Type to that of the Drop impl.
- //
- // self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x}
- //
- // Applying this to the predicates (i.e., assumptions) provided by the item
- // definition yields the instantiated assumptions:
- //
- // ['y : 'z]
+ let infcx = tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(&infcx);
+
+ // Take the param-env of the adt and substitute the substs that show up in
+ // the implementation's self type. This gives us the assumptions that the
+ // self ty of the implementation is allowed to know just from it being a
+ // well-formed adt, since that's all we're allowed to assume while proving
+ // the Drop implementation is not specialized.
//
- // We then check all of the predicates of the Drop impl:
- //
- // ['y:'z, 'x:'y]
- //
- // and ensure each is in the list of instantiated
- // assumptions. Here, `'y:'z` is present, but `'x:'y` is
- // absent. So we report an error that the Drop impl injected a
- // predicate that is not present on the struct definition.
-
- // We can assume the predicates attached to struct/enum definition
- // hold.
- let generic_assumptions = tcx.predicates_of(self_type_did);
-
- let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
- let assumptions_in_impl_context = assumptions_in_impl_context.predicates;
-
- debug!(?assumptions_in_impl_context, ?dtor_predicates.predicates);
-
- let self_param_env = tcx.param_env(self_type_did);
-
- // An earlier version of this code attempted to do this checking
- // via the traits::fulfill machinery. However, it ran into trouble
- // since the fulfill machinery merely turns outlives-predicates
- // 'a:'b and T:'b into region inference constraints. It is simpler
- // just to look for all the predicates directly.
-
- assert_eq!(dtor_predicates.parent, None);
- for &(predicate, predicate_sp) in dtor_predicates.predicates {
- // (We do not need to worry about deep analysis of type
- // expressions etc because the Drop impls are already forced
- // to take on a structure that is roughly an alpha-renaming of
- // the generic parameters of the item definition.)
-
- // This path now just checks *all* predicates via an instantiation of
- // the `SimpleEqRelation`, which simply forwards to the `relate` machinery
- // after taking care of anonymizing late bound regions.
- //
- // However, it may be more efficient in the future to batch
- // the analysis together via the fulfill (see comment above regarding
- // the usage of the fulfill machinery), rather than the
- // repeated `.iter().any(..)` calls.
+ // We don't need to normalize this param-env or anything, since we're only
+ // substituting it with free params, so no additional param-env normalization
+ // can occur on top of what has been done in the param_env query itself.
+ let param_env = ty::EarlyBinder(tcx.param_env(adt_def_id))
+ .subst(tcx, adt_to_impl_substs)
+ .with_constness(tcx.constness(drop_impl_def_id));
+
+ for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
+ let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
+ let pred = ocx.normalize(&normalize_cause, param_env, pred);
+ let cause = traits::ObligationCause::new(span, adt_def_id, traits::DropImpl);
+ ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, pred));
+ }
- // This closure is a more robust way to check `Predicate` equality
- // than simple `==` checks (which were the previous implementation).
- // It relies on `ty::relate` for `TraitPredicate`, `ProjectionPredicate`,
- // `ConstEvaluatable` and `TypeOutlives` (which implement the Relate trait),
- // while delegating on simple equality for the other `Predicate`.
- // This implementation solves (Issue #59497) and (Issue #58311).
- // It is unclear to me at the moment whether the approach based on `relate`
- // could be extended easily also to the other `Predicate`.
- let predicate_matches_closure = |p: Predicate<'tcx>| {
- let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
- let predicate = predicate.kind();
- let p = p.kind();
- match (predicate.skip_binder(), p.skip_binder()) {
- (
- ty::PredicateKind::Clause(ty::Clause::Trait(a)),
- ty::PredicateKind::Clause(ty::Clause::Trait(b)),
- ) => relator.relate(predicate.rebind(a), p.rebind(b)).is_ok(),
- (
- ty::PredicateKind::Clause(ty::Clause::Projection(a)),
- ty::PredicateKind::Clause(ty::Clause::Projection(b)),
- ) => relator.relate(predicate.rebind(a), p.rebind(b)).is_ok(),
- (
- ty::PredicateKind::ConstEvaluatable(a),
- ty::PredicateKind::ConstEvaluatable(b),
- ) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
- (
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- ty_a,
- lt_a,
- ))),
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- ty_b,
- lt_b,
- ))),
- ) => {
- relator.relate(predicate.rebind(ty_a), p.rebind(ty_b)).is_ok()
- && relator.relate(predicate.rebind(lt_a), p.rebind(lt_b)).is_ok()
- }
- (ty::PredicateKind::WellFormed(arg_a), ty::PredicateKind::WellFormed(arg_b)) => {
- relator.relate(predicate.rebind(arg_a), p.rebind(arg_b)).is_ok()
- }
- _ => predicate == p,
+ // All of the custom error reporting logic is to preserve parity with the old
+ // error messages.
+ //
+ // They can probably get removed with better treatment of the new `DropImpl`
+ // obligation cause code, and perhaps some custom logic in `report_region_errors`.
+
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ let mut guar = None;
+ let mut root_predicates = FxHashSet::default();
+ for error in errors {
+ let root_predicate = error.root_obligation.predicate;
+ if root_predicates.insert(root_predicate) {
+ let item_span = tcx.def_span(adt_def_id);
+ let self_descr = tcx.def_descr(adt_def_id.to_def_id());
+ guar = Some(
+ struct_span_err!(
+ tcx.sess,
+ error.root_obligation.cause.span,
+ E0367,
+ "`Drop` impl requires `{root_predicate}` \
+ but the {self_descr} it is implemented for does not",
+ )
+ .span_note(item_span, "the implementor must specify the same requirement")
+ .emit(),
+ );
}
- };
-
- if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) {
- let item_span = tcx.def_span(self_type_did);
- let self_descr = tcx.def_descr(self_type_did.to_def_id());
- let reported = struct_span_err!(
- tcx.sess,
- predicate_sp,
- E0367,
- "`Drop` impl requires `{predicate}` but the {self_descr} it is implemented for does not",
- )
- .span_note(item_span, "the implementor must specify the same requirement")
- .emit();
- result = Err(reported);
}
+ return Err(guar.unwrap());
}
- result
-}
-
-/// This is an implementation of the [`TypeRelation`] trait with the
-/// aim of simply comparing for equality (without side-effects).
-///
-/// It is not intended to be used anywhere else other than here.
-pub(crate) struct SimpleEqRelation<'tcx> {
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
-}
-
-impl<'tcx> SimpleEqRelation<'tcx> {
- fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> SimpleEqRelation<'tcx> {
- SimpleEqRelation { tcx, param_env }
- }
-}
-
-impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
- }
-
- fn tag(&self) -> &'static str {
- "dropck::SimpleEqRelation"
- }
-
- fn a_is_expected(&self) -> bool {
- true
- }
-
- fn relate_with_variance<T: Relate<'tcx>>(
- &mut self,
- _: ty::Variance,
- _info: ty::VarianceDiagInfo<'tcx>,
- a: T,
- b: T,
- ) -> RelateResult<'tcx, T> {
- // Here we ignore variance because we require drop impl's types
- // to be *exactly* the same as to the ones in the struct definition.
- self.relate(a, b)
- }
-
- fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
- debug!("SimpleEqRelation::tys(a={:?}, b={:?})", a, b);
- ty::relate::super_relate_tys(self, a, b)
- }
-
- fn regions(
- &mut self,
- a: ty::Region<'tcx>,
- b: ty::Region<'tcx>,
- ) -> RelateResult<'tcx, ty::Region<'tcx>> {
- debug!("SimpleEqRelation::regions(a={:?}, b={:?})", a, b);
-
- // We can just equate the regions because LBRs have been
- // already anonymized.
- if a == b {
- Ok(a)
- } else {
- // I'm not sure is this `TypeError` is the right one, but
- // it should not matter as it won't be checked (the dropck
- // will emit its own, more informative and higher-level errors
- // in case anything goes wrong).
- Err(TypeError::RegionsPlaceholderMismatch)
+ let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(param_env));
+ if !errors.is_empty() {
+ let mut guar = None;
+ for error in errors {
+ let item_span = tcx.def_span(adt_def_id);
+ let self_descr = tcx.def_descr(adt_def_id.to_def_id());
+ let outlives = match error {
+ RegionResolutionError::ConcreteFailure(_, a, b) => format!("{b}: {a}"),
+ RegionResolutionError::GenericBoundFailure(_, generic, r) => {
+ format!("{generic}: {r}")
+ }
+ RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => format!("{b}: {a}"),
+ RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
+ format!("{b}: {a}", a = tcx.mk_re_var(a))
+ }
+ };
+ guar = Some(
+ struct_span_err!(
+ tcx.sess,
+ error.origin().span(),
+ E0367,
+ "`Drop` impl requires `{outlives}` \
+ but the {self_descr} it is implemented for does not",
+ )
+ .span_note(item_span, "the implementor must specify the same requirement")
+ .emit(),
+ );
}
+ return Err(guar.unwrap());
}
- fn consts(
- &mut self,
- a: ty::Const<'tcx>,
- b: ty::Const<'tcx>,
- ) -> RelateResult<'tcx, ty::Const<'tcx>> {
- debug!("SimpleEqRelation::consts(a={:?}, b={:?})", a, b);
- ty::relate::super_relate_consts(self, a, b)
- }
-
- fn binders<T>(
- &mut self,
- a: ty::Binder<'tcx, T>,
- b: ty::Binder<'tcx, T>,
- ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
- where
- T: Relate<'tcx>,
- {
- debug!("SimpleEqRelation::binders({:?}: {:?}", a, b);
-
- // Anonymizing the LBRs is necessary to solve (Issue #59497).
- // After we do so, it should be totally fine to skip the binders.
- let anon_a = self.tcx.anonymize_bound_vars(a);
- let anon_b = self.tcx.anonymize_bound_vars(b);
- self.relate(anon_a.skip_binder(), anon_b.skip_binder())?;
-
- Ok(a)
- }
+ Ok(())
}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 854974d16..e8785235c 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -198,7 +198,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
| sym::assert_zero_valid
| sym::assert_mem_uninitialized_valid => (1, Vec::new(), tcx.mk_unit()),
sym::forget => (1, vec![param(0)], tcx.mk_unit()),
- sym::transmute => (2, vec![param(0)], param(1)),
+ sym::transmute | sym::transmute_unchecked => (2, vec![param(0)], param(1)),
sym::prefetch_read_data
| sym::prefetch_write_data
| sym::prefetch_read_instruction
@@ -215,7 +215,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
sym::type_id => (1, Vec::new(), tcx.types.u64),
- sym::offset | sym::arith_offset => (
+ sym::offset => (2, vec![param(0), param(1)], param(0)),
+ sym::arith_offset => (
1,
vec![
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@@ -380,6 +381,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
+ sym::write_via_move => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
sym::discriminant_value => {
let assoc_items = tcx.associated_item_def_ids(
@@ -545,14 +547,14 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
Err(_) => {
let msg =
format!("unrecognized platform-specific intrinsic function: `{name}`");
- tcx.sess.struct_span_err(it.span, &msg).emit();
+ tcx.sess.struct_span_err(it.span, msg).emit();
return;
}
}
}
_ => {
let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
- tcx.sess.struct_span_err(it.span, &msg).emit();
+ tcx.sess.struct_span_err(it.span, msg).emit();
return;
}
};
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 0d482b53a..0bb1467ef 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -84,33 +84,45 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Adt(adt, substs) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
- match elem_ty.kind() {
- ty::Never | ty::Error(_) => return None,
- ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => {
- Some(InlineAsmType::VecI8(fields.len() as u64))
+
+ let (size, ty) = match elem_ty.kind() {
+ ty::Array(ty, len) => {
+ if let Some(len) =
+ len.try_eval_target_usize(self.tcx, self.tcx.param_env(adt.did()))
+ {
+ (len, *ty)
+ } else {
+ return None;
+ }
}
+ _ => (fields.len() as u64, elem_ty),
+ };
+
+ match ty.kind() {
+ ty::Never | ty::Error(_) => return None,
+ ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::VecI8(size)),
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => {
- Some(InlineAsmType::VecI16(fields.len() as u64))
+ Some(InlineAsmType::VecI16(size))
}
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => {
- Some(InlineAsmType::VecI32(fields.len() as u64))
+ Some(InlineAsmType::VecI32(size))
}
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => {
- Some(InlineAsmType::VecI64(fields.len() as u64))
+ Some(InlineAsmType::VecI64(size))
}
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => {
- Some(InlineAsmType::VecI128(fields.len() as u64))
+ Some(InlineAsmType::VecI128(size))
}
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => {
Some(match self.tcx.sess.target.pointer_width {
- 16 => InlineAsmType::VecI16(fields.len() as u64),
- 32 => InlineAsmType::VecI32(fields.len() as u64),
- 64 => InlineAsmType::VecI64(fields.len() as u64),
+ 16 => InlineAsmType::VecI16(size),
+ 32 => InlineAsmType::VecI32(size),
+ 64 => InlineAsmType::VecI64(size),
_ => unreachable!(),
})
}
- ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(fields.len() as u64)),
- ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(fields.len() as u64)),
+ ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
+ ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
_ => None,
}
}
@@ -118,7 +130,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
_ => None,
};
let Some(asm_ty) = asm_ty else {
- let msg = &format!("cannot use value of type `{ty}` for inline assembly");
+ let msg = format!("cannot use value of type `{ty}` for inline assembly");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(
"only integers, floats, SIMD vectors, pointers and function pointers \
@@ -133,7 +145,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
let msg = "arguments for inline assembly must be copyable";
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
- err.note(&format!("`{ty}` does not implement the Copy trait"));
+ err.note(format!("`{ty}` does not implement the Copy trait"));
err.emit();
}
@@ -152,8 +164,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let mut err = self.tcx.sess.struct_span_err(vec![in_expr.span, expr.span], msg);
let in_expr_ty = (self.get_operand_ty)(in_expr);
- err.span_label(in_expr.span, &format!("type `{in_expr_ty}`"));
- err.span_label(expr.span, &format!("type `{ty}`"));
+ err.span_label(in_expr.span, format!("type `{in_expr_ty}`"));
+ err.span_label(expr.span, format!("type `{ty}`"));
err.note(
"asm inout arguments must have the same type, \
unless they are both pointers or integers of the same size",
@@ -172,17 +184,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let reg_class = reg.reg_class();
let supported_tys = reg_class.supported_types(asm_arch);
let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
- let msg = &format!("type `{ty}` cannot be used with this register class");
+ let msg = format!("type `{ty}` cannot be used with this register class");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
let supported_tys: Vec<_> =
supported_tys.iter().map(|(t, _)| t.to_string()).collect();
- err.note(&format!(
+ err.note(format!(
"register class `{}` supports these types: {}",
reg_class.name(),
supported_tys.join(", "),
));
if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) {
- err.help(&format!(
+ err.help(format!(
"consider using the `{}` register class instead",
suggest.name()
));
@@ -203,9 +215,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// register class is usable at all.
if let Some(feature) = feature {
if !target_features.contains(feature) {
- let msg = &format!("`{}` target feature is not enabled", feature);
+ let msg = format!("`{}` target feature is not enabled", feature);
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
- err.note(&format!(
+ err.note(format!(
"this is required to use type `{}` with register class `{}`",
ty,
reg_class.name(),
@@ -240,10 +252,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
"formatting may not be suitable for sub-register argument",
|lint| {
lint.span_label(expr.span, "for this argument");
- lint.help(&format!(
+ lint.help(format!(
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}`",
));
- lint.help(&format!(
+ lint.help(format!(
"or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`",
));
lint
@@ -289,7 +301,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
op.is_clobber(),
) {
let msg = format!("cannot use register `{}`: {}", reg.name(), msg);
- self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
+ self.tcx.sess.struct_span_err(*op_sp, msg).emit();
continue;
}
}
@@ -328,7 +340,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
reg_class.name(),
feature
);
- self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
+ self.tcx.sess.struct_span_err(*op_sp, msg).emit();
// register isn't enabled, don't do more checks
continue;
}
@@ -342,7 +354,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
.intersperse(", ")
.collect::<String>(),
);
- self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
+ self.tcx.sess.struct_span_err(*op_sp, msg).emit();
// register isn't enabled, don't do more checks
continue;
}
@@ -424,7 +436,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
err.span_label(
self.tcx.def_span(anon_const.def_id),
- &format!("is {} `{}`", ty.kind().article(), ty),
+ format!("is {} `{}`", ty.kind().article(), ty),
);
err.help("`sym` operands must refer to either a function or a static");
err.emit();
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 8fe4c44fc..3971a4c01 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -74,11 +74,11 @@ pub use check::check_abi;
use check::check_mod_item_types;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_session::parse::feature_err;
@@ -90,6 +90,7 @@ use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
use std::num::NonZeroU32;
+use crate::errors;
use crate::require_c_abi_if_c_variadic;
use crate::util::common::indenter;
@@ -171,34 +172,18 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
let span = tcx.def_span(impl_item);
let ident = tcx.item_name(impl_item);
- let mut err = struct_span_err!(
- tcx.sess,
- span,
- E0520,
- "`{}` specializes an item from a parent `impl`, but that item is not marked `default`",
- ident,
- );
- err.span_label(span, format!("cannot specialize default item `{}`", ident));
-
- match tcx.span_of_impl(parent_impl) {
- Ok(span) => {
- err.span_label(span, "parent `impl` is here");
- err.note(&format!(
- "to specialize, `{}` in the parent `impl` must be marked `default`",
- ident
- ));
- }
- Err(cname) => {
- err.note(&format!("parent implementation is in crate `{cname}`"));
- }
- }
- err.emit();
+ let err = match tcx.span_of_impl(parent_impl) {
+ Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp },
+ Err(cname) => errors::ImplNotMarkedDefault::Err { span, ident, cname },
+ };
+
+ tcx.sess.emit_err(err);
}
fn missing_items_err(
tcx: TyCtxt<'_>,
- impl_span: Span,
+ impl_def_id: LocalDefId,
missing_items: &[ty::AssocItem],
full_impl_span: Span,
) {
@@ -211,14 +196,6 @@ fn missing_items_err(
.collect::<Vec<_>>()
.join("`, `");
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0046,
- "not all trait items implemented, missing: `{missing_items_msg}`",
- );
- err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation"));
-
// `Span` before impl block closing brace.
let hi = full_impl_span.hi() - BytePos(1);
// Point at the place right before the closing brace of the relevant `impl` to suggest
@@ -227,20 +204,40 @@ fn missing_items_err(
// Obtain the level of indentation ending in `sugg_sp`.
let padding =
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
+ let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
+ (Vec::new(), Vec::new(), Vec::new());
for &trait_item in missing_items {
- let snippet = suggestion_signature(trait_item, tcx);
+ let snippet = suggestion_signature(
+ tcx,
+ trait_item,
+ tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(),
+ );
let code = format!("{}{}\n{}", padding, snippet, padding);
- let msg = format!("implement the missing item: `{snippet}`");
- let appl = Applicability::HasPlaceholders;
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
- err.span_label(span, format!("`{}` from trait", trait_item.name));
- err.tool_only_span_suggestion(sugg_sp, &msg, code, appl);
+ missing_trait_item_label
+ .push(errors::MissingTraitItemLabel { span, item: trait_item.name });
+ missing_trait_item.push(errors::MissingTraitItemSuggestion {
+ span: sugg_sp,
+ code,
+ snippet,
+ });
} else {
- err.span_suggestion_hidden(sugg_sp, &msg, code, appl);
+ missing_trait_item_none.push(errors::MissingTraitItemSuggestionNone {
+ span: sugg_sp,
+ code,
+ snippet,
+ })
}
}
- err.emit();
+
+ tcx.sess.emit_err(errors::MissingTraitItem {
+ span: tcx.span_of_impl(impl_def_id.to_def_id()).unwrap(),
+ missing_items_msg,
+ missing_trait_item_label,
+ missing_trait_item,
+ missing_trait_item_none,
+ });
}
fn missing_items_must_implement_one_of_err(
@@ -252,19 +249,11 @@ fn missing_items_must_implement_one_of_err(
let missing_items_msg =
missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `");
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0046,
- "not all trait items implemented, missing one of: `{missing_items_msg}`",
- );
- err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation"));
-
- if let Some(annotation_span) = annotation_span {
- err.span_note(annotation_span, "required because of this annotation");
- }
-
- err.emit();
+ tcx.sess.emit_err(errors::MissingOneOfTraitItem {
+ span: impl_span,
+ note: annotation_span,
+ missing_items_msg,
+ });
}
fn default_body_is_unstable(
@@ -276,36 +265,42 @@ fn default_body_is_unstable(
issue: Option<NonZeroU32>,
) {
let missing_item_name = tcx.associated_item(item_did).name;
- let use_of_unstable_library_feature_note = match reason {
- Some(r) => format!("use of unstable library feature '{feature}': {r}"),
- None => format!("use of unstable library feature '{feature}'"),
+ let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new());
+ match reason {
+ Some(r) => {
+ some_note = true;
+ reason_str = r.to_string();
+ }
+ None => none_note = true,
};
- let mut err = struct_span_err!(
- tcx.sess,
- impl_span,
- E0046,
- "not all trait items implemented, missing: `{missing_item_name}`",
- );
- err.note(format!("default implementation of `{missing_item_name}` is unstable"));
- err.note(use_of_unstable_library_feature_note);
+ let mut err = tcx.sess.create_err(errors::MissingTraitItemUnstable {
+ span: impl_span,
+ some_note,
+ none_note,
+ missing_item_name,
+ feature,
+ reason: reason_str,
+ });
+
rustc_session::parse::add_feature_diagnostics_for_issue(
&mut err,
&tcx.sess.parse_sess,
feature,
rustc_feature::GateIssue::Library(issue),
);
+
err.emit();
}
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
fn bounds_from_generic_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- predicates: ty::GenericPredicates<'tcx>,
+ predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> (String, String) {
let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
let mut projections = vec![];
- for (predicate, _) in predicates.predicates {
+ for (predicate, _) in predicates {
debug!("predicate {:?}", predicate);
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
@@ -367,7 +362,7 @@ fn fn_sig_suggestion<'tcx>(
tcx: TyCtxt<'tcx>,
sig: ty::FnSig<'tcx>,
ident: Ident,
- predicates: ty::GenericPredicates<'tcx>,
+ predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
assoc: ty::AssocItem,
) -> String {
let args = sig
@@ -436,7 +431,17 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
/// Return placeholder code for the given associated item.
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
/// structured suggestion.
-fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
+fn suggestion_signature<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ assoc: ty::AssocItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
+) -> String {
+ let substs = ty::InternalSubsts::identity_for_item(tcx, assoc.def_id).rebase_onto(
+ tcx,
+ assoc.container_id(tcx),
+ impl_trait_ref.with_self_ty(tcx, tcx.types.self_param).substs,
+ );
+
match assoc.kind {
ty::AssocKind::Fn => {
// We skip the binder here because the binder would deanonymize all
@@ -445,16 +450,22 @@ fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
// regions just fine, showing `fn(&MyType)`.
fn_sig_suggestion(
tcx,
- tcx.fn_sig(assoc.def_id).subst_identity().skip_binder(),
+ tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
assoc,
)
}
- ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
+ ty::AssocKind::Type => {
+ let (generics, where_clauses) = bounds_from_generic_predicates(
+ tcx,
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ );
+ format!("type {}{generics} = /* Type */{where_clauses};", assoc.name)
+ }
ty::AssocKind::Const => {
let ty = tcx.type_of(assoc.def_id).subst_identity();
- let val = ty_kind_suggestion(ty).unwrap_or("value");
+ let val = ty_kind_suggestion(ty).unwrap_or("todo!()");
format!("const {}: {} = {};", assoc.name, ty, val)
}
}
@@ -467,16 +478,18 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d
.iter()
.map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap())
.collect();
- let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),);
- let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}");
- err.span_label(sp, &msg);
+ let (mut spans, mut many) = (Vec::new(), None);
if let [start @ .., end] = &*variant_spans {
- for variant_span in start {
- err.span_label(*variant_span, "");
- }
- err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
+ spans = start.to_vec();
+ many = Some(*end);
}
- err.emit();
+ tcx.sess.emit_err(errors::TransparentEnumVariant {
+ span: sp,
+ spans,
+ many,
+ number: adt.variants().len(),
+ path: tcx.def_path_str(did),
+ });
}
/// Emit an error when encountering two or more non-zero-sized fields in a transparent
@@ -488,21 +501,21 @@ fn bad_non_zero_sized_fields<'tcx>(
field_spans: impl Iterator<Item = Span>,
sp: Span,
) {
- let msg = format!("needs at most one non-zero-sized field, but has {field_count}");
- let mut err = struct_span_err!(
- tcx.sess,
- sp,
- E0690,
- "{}transparent {} {}",
- if adt.is_enum() { "the variant of a " } else { "" },
- adt.descr(),
- msg,
- );
- err.span_label(sp, &msg);
- for sp in field_spans {
- err.span_label(sp, "this field is non-zero-sized");
+ if adt.is_enum() {
+ tcx.sess.emit_err(errors::TransparentNonZeroSizedEnum {
+ span: sp,
+ spans: field_spans.collect(),
+ field_count,
+ desc: adt.descr(),
+ });
+ } else {
+ tcx.sess.emit_err(errors::TransparentNonZeroSized {
+ span: sp,
+ spans: field_spans.collect(),
+ field_count,
+ desc: adt.descr(),
+ });
}
- err.emit();
}
// FIXME: Consider moving this method to a more fitting place.
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index b28bfb1d5..6ab5556e9 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -12,7 +12,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt};
-use rustc_index::vec::Idx;
+use rustc_index::Idx;
use rustc_middle::middle::region::*;
use rustc_middle::ty::TyCtxt;
use rustc_span::source_map;
@@ -421,7 +421,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
let target_scopes = visitor.fixup_scopes.drain(start_point..);
for scope in target_scopes {
- let mut yield_data =
+ let yield_data =
visitor.scope_tree.yield_in_scope.get_mut(&scope).unwrap().last_mut().unwrap();
let count = yield_data.expr_and_pat_count;
let span = yield_data.span;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 53197bc84..b403ee96b 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -12,7 +12,7 @@ use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
use rustc_infer::infer::outlives::obligations::TypeOutlives;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
@@ -155,7 +155,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
debug!(
?item.owner_id,
- item.name = ? tcx.def_path_str(def_id.to_def_id())
+ item.name = ? tcx.def_path_str(def_id)
);
match item.kind {
@@ -179,7 +179,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
hir::ItemKind::Impl(impl_) => {
let is_auto = tcx
.impl_trait_ref(def_id)
- .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
+ .is_some_and(|trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id));
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
let mut err =
@@ -251,7 +251,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
debug!(
?item.owner_id,
- item.name = ? tcx.def_path_str(def_id.to_def_id())
+ item.name = ? tcx.def_path_str(def_id)
);
match item.kind {
@@ -360,7 +360,9 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
tcx,
param_env,
item_def_id,
- tcx.explicit_item_bounds(item_def_id).to_vec(),
+ tcx.explicit_item_bounds(item_def_id)
+ .subst_identity_iter_copied()
+ .collect::<Vec<_>>(),
&FxIndexSet::default(),
gat_def_id.def_id,
gat_generics,
@@ -443,7 +445,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let plural = pluralize!(unsatisfied_bounds.len());
let mut err = tcx.sess.struct_span_err(
gat_item_hir.span,
- &format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
+ format!("missing required bound{} on `{}`", plural, gat_item_hir.ident),
);
let suggestion = format!(
@@ -453,14 +455,14 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
);
err.span_suggestion(
gat_item_hir.generics.tail_span_for_predicate_suggestion(),
- &format!("add the required where clause{plural}"),
+ format!("add the required where clause{plural}"),
suggestion,
Applicability::MachineApplicable,
);
let bound =
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
- err.note(&format!(
+ err.note(format!(
"{} currently required to ensure that impls have maximum flexibility",
bound
));
@@ -914,14 +916,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
if is_ptr {
tcx.sess.span_err(
hir_ty.span,
- &format!(
+ format!(
"using {unsupported_type} as const generic parameters is forbidden",
),
);
} else {
let mut err = tcx.sess.struct_span_err(
hir_ty.span,
- &format!(
+ format!(
"{unsupported_type} is forbidden as the type of a const generic parameter",
),
);
@@ -1025,9 +1027,9 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
packed && {
let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
let ty = tcx.erase_regions(ty);
- if ty.needs_infer() {
+ if ty.has_infer() {
tcx.sess
- .delay_span_bug(item.span, &format!("inference variables in {:?}", ty));
+ .delay_span_bug(item.span, format!("inference variables in {:?}", ty));
// Just treat unresolved type expression as if it needs drop.
true
} else {
@@ -1125,7 +1127,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
debug!("check_associated_type_bounds: bounds={:?}", bounds);
- let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
+ let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| {
let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations(
wfcx.infcx,
@@ -1290,7 +1292,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
// Ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
- if !ty.needs_subst() {
+ if !ty.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
Some(WellFormedLoc::Ty(param.def_id.expect_local())),
@@ -1306,7 +1308,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
// we should eagerly error.
let default_ct = tcx.const_param_default(param.def_id).subst_identity();
- if !default_ct.needs_subst() {
+ if !default_ct.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
None,
@@ -1340,7 +1342,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
if is_our_default(param) {
let default_ty = tcx.type_of(param.def_id).subst_identity();
// ... and it's not a dependent default, ...
- if !default_ty.needs_subst() {
+ if !default_ty.has_param() {
// ... then substitute it with the default.
return default_ty.into();
}
@@ -1353,7 +1355,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
if is_our_default(param) {
let default_ct = tcx.const_param_default(param.def_id).subst_identity();
// ... and it's not a dependent default, ...
- if !default_ct.needs_subst() {
+ if !default_ct.has_param() {
// ... then substitute it with the default.
return default_ct.into();
}
@@ -1574,21 +1576,14 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
&& source == self.fn_def_id
{
- let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
- if let ty::ReLateBound(index, bv) = re.kind() {
- if depth != ty::INNERMOST {
- return tcx.mk_re_error_with_message(
- DUMMY_SP,
- "we shouldn't walk non-predicate binders with `impl Trait`...",
- );
- }
- tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
- } else {
- re
+ let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
+ match re.kind() {
+ ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) => re,
+ r => bug!("unexpected region: {r:?}"),
}
});
for (bound, bound_span) in tcx
- .bound_explicit_item_bounds(opaque_ty.def_id)
+ .explicit_item_bounds(opaque_ty.def_id)
.subst_iter_copied(tcx, opaque_ty.substs)
{
let bound = self.wfcx.normalize(bound_span, None, bound);
@@ -1656,7 +1651,7 @@ fn check_method_receiver<'tcx>(
&tcx.sess.parse_sess,
sym::arbitrary_self_types,
span,
- &format!(
+ format!(
"`{receiver_ty}` cannot be used as the type of `self` without \
the `arbitrary_self_types` feature",
),
@@ -1784,7 +1779,7 @@ fn receiver_is_implemented<'tcx>(
receiver_ty: Ty<'tcx>,
) -> bool {
let tcx = wfcx.tcx();
- let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(receiver_trait_def_id, [receiver_ty]));
+ let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]);
let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref);
@@ -1879,10 +1874,10 @@ fn report_bivariance(
} else {
format!("consider removing `{param_name}` or referring to it in a field")
};
- err.help(&msg);
+ err.help(msg);
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
- err.help(&format!(
+ err.help(format!(
"if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
param_name
));
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 0f40cca94..a98d8e171 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -1,9 +1,11 @@
//! Check properties that are required by built-in traits and set
//! up data structures required by type-checking/codegen.
-use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
+use crate::errors::{
+ ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem,
+};
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_err, MultiSpan};
+use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
@@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
use rustc_infer::traits::Obligation;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::misc::{
- type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
+ type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
+ ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
};
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCause};
@@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
Checker { tcx, trait_def_id }
.check(lang_items.drop_trait(), visit_implementation_of_drop)
.check(lang_items.copy_trait(), visit_implementation_of_copy)
+ .check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty)
.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
}
@@ -74,120 +79,16 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
- let span = match tcx.hir().expect_item(impl_did).kind {
- ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
- ItemKind::Impl(impl_) => impl_.self_ty.span,
- _ => bug!("expected Copy impl item"),
+ let span = match tcx.hir().expect_item(impl_did).expect_impl() {
+ hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
+ hir::Impl { self_ty, .. } => self_ty.span,
};
let cause = traits::ObligationCause::misc(span, impl_did);
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
Ok(()) => {}
- Err(CopyImplementationError::InfrigingFields(fields)) => {
- let mut err = struct_span_err!(
- tcx.sess,
- span,
- E0204,
- "the trait `Copy` cannot be implemented for this type"
- );
-
- // We'll try to suggest constraining type parameters to fulfill the requirements of
- // their `Copy` implementation.
- let mut errors: BTreeMap<_, Vec<_>> = Default::default();
- let mut bounds = vec![];
-
- let mut seen_tys = FxHashSet::default();
-
- for (field, ty, reason) in fields {
- // Only report an error once per type.
- if !seen_tys.insert(ty) {
- continue;
- }
-
- let field_span = tcx.def_span(field.did);
- err.span_label(field_span, "this field does not implement `Copy`");
-
- match reason {
- InfringingFieldsReason::Fulfill(fulfillment_errors) => {
- for error in fulfillment_errors {
- let error_predicate = error.obligation.predicate;
- // Only note if it's not the root obligation, otherwise it's trivial and
- // should be self-explanatory (i.e. a field literally doesn't implement Copy).
-
- // FIXME: This error could be more descriptive, especially if the error_predicate
- // contains a foreign type or if it's a deeply nested type...
- if error_predicate != error.root_obligation.predicate {
- errors
- .entry((ty.to_string(), error_predicate.to_string()))
- .or_default()
- .push(error.obligation.cause.span);
- }
- if let ty::PredicateKind::Clause(ty::Clause::Trait(
- ty::TraitPredicate {
- trait_ref,
- polarity: ty::ImplPolarity::Positive,
- ..
- },
- )) = error_predicate.kind().skip_binder()
- {
- let ty = trait_ref.self_ty();
- if let ty::Param(_) = ty.kind() {
- bounds.push((
- format!("{ty}"),
- trait_ref.print_only_trait_path().to_string(),
- Some(trait_ref.def_id),
- ));
- }
- }
- }
- }
- InfringingFieldsReason::Regions(region_errors) => {
- for error in region_errors {
- let ty = ty.to_string();
- match error {
- RegionResolutionError::ConcreteFailure(origin, a, b) => {
- let predicate = format!("{b}: {a}");
- errors
- .entry((ty.clone(), predicate.clone()))
- .or_default()
- .push(origin.span());
- if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
- bounds.push((b.to_string(), a.to_string(), None));
- }
- }
- RegionResolutionError::GenericBoundFailure(origin, a, b) => {
- let predicate = format!("{a}: {b}");
- errors
- .entry((ty.clone(), predicate.clone()))
- .or_default()
- .push(origin.span());
- if let infer::region_constraints::GenericKind::Param(_) = a {
- bounds.push((a.to_string(), b.to_string(), None));
- }
- }
- _ => continue,
- }
- }
- }
- }
- }
- for ((ty, error_predicate), spans) in errors {
- let span: MultiSpan = spans.into();
- err.span_note(
- span,
- &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
- );
- }
- suggest_constraining_type_params(
- tcx,
- tcx.hir().get_generics(impl_did).expect("impls always have generics"),
- &mut err,
- bounds.iter().map(|(param, constraint, def_id)| {
- (param.as_str(), constraint.as_str(), *def_id)
- }),
- None,
- );
- err.emit();
+ Err(CopyImplementationError::InfringingFields(fields)) => {
+ infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span);
}
Err(CopyImplementationError::NotAnAdt) => {
tcx.sess.emit_err(CopyImplOnNonAdt { span });
@@ -198,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
}
}
+fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
+ let self_type = tcx.type_of(impl_did).subst_identity();
+ assert!(!self_type.has_escaping_bound_vars());
+
+ let param_env = tcx.param_env(impl_did);
+
+ let span = match tcx.hir().expect_item(impl_did).expect_impl() {
+ hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
+ impl_ => impl_.self_ty.span,
+ };
+
+ let cause = traits::ObligationCause::misc(span, impl_did);
+ match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
+ Ok(()) => {}
+ Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
+ infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span);
+ }
+ Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
+ tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span });
+ }
+ }
+}
+
fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
@@ -289,7 +213,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
for structs containing the field being coerced, \
ZST fields with 1 byte alignment, and nothing else",
)
- .note(&format!(
+ .note(format!(
"extra field `{}` of type `{}` is not allowed",
field.name, ty_a,
))
@@ -317,7 +241,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
for a coercion between structures with a single field \
being coerced",
)
- .note(&format!(
+ .note(format!(
"currently, {} fields need coercions: {}",
coerced_fields.len(),
coerced_fields
@@ -341,10 +265,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
tcx,
cause.clone(),
param_env,
- ty::Binder::dummy(tcx.mk_trait_ref(
+ ty::TraitRef::new(
+ tcx,
dispatch_from_dyn_trait,
[field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
- )),
+ ),
));
}
let errors = ocx.select_all_or_error();
@@ -373,9 +298,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
- let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
- tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
- });
+ let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
let source = tcx.type_of(impl_did).subst_identity();
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
@@ -545,7 +468,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
"`CoerceUnsized` may only be implemented for \
a coercion between structures with one field being coerced",
)
- .note(&format!(
+ .note(format!(
"currently, {} fields need coercions: {}",
diff_fields.len(),
diff_fields
@@ -580,8 +503,12 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
// Register an obligation for `A: Trait<B>`.
let ocx = ObligationCtxt::new(&infcx);
let cause = traits::ObligationCause::misc(span, impl_did);
- let obligation =
- Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target]));
+ let obligation = Obligation::new(
+ tcx,
+ cause,
+ param_env,
+ ty::TraitRef::new(tcx, trait_def_id, [source, target]),
+ );
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
@@ -594,3 +521,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
CoerceUnsizedInfo { custom_kind: kind }
}
+
+fn infringing_fields_error(
+ tcx: TyCtxt<'_>,
+ fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>,
+ lang_item: LangItem,
+ impl_did: LocalDefId,
+ impl_span: Span,
+) -> ErrorGuaranteed {
+ let trait_did = tcx.require_lang_item(lang_item, Some(impl_span));
+
+ let trait_name = tcx.def_path_str(trait_did);
+
+ let mut err = struct_span_err!(
+ tcx.sess,
+ impl_span,
+ E0204,
+ "the trait `{trait_name}` cannot be implemented for this type"
+ );
+
+ // We'll try to suggest constraining type parameters to fulfill the requirements of
+ // their `Copy` implementation.
+ let mut errors: BTreeMap<_, Vec<_>> = Default::default();
+ let mut bounds = vec![];
+
+ let mut seen_tys = FxHashSet::default();
+
+ for (field, ty, reason) in fields {
+ // Only report an error once per type.
+ if !seen_tys.insert(ty) {
+ continue;
+ }
+
+ let field_span = tcx.def_span(field.did);
+ err.span_label(field_span, format!("this field does not implement `{trait_name}`"));
+
+ match reason {
+ InfringingFieldsReason::Fulfill(fulfillment_errors) => {
+ for error in fulfillment_errors {
+ let error_predicate = error.obligation.predicate;
+ // Only note if it's not the root obligation, otherwise it's trivial and
+ // should be self-explanatory (i.e. a field literally doesn't implement Copy).
+
+ // FIXME: This error could be more descriptive, especially if the error_predicate
+ // contains a foreign type or if it's a deeply nested type...
+ if error_predicate != error.root_obligation.predicate {
+ errors
+ .entry((ty.to_string(), error_predicate.to_string()))
+ .or_default()
+ .push(error.obligation.cause.span);
+ }
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ trait_ref,
+ polarity: ty::ImplPolarity::Positive,
+ ..
+ })) = error_predicate.kind().skip_binder()
+ {
+ let ty = trait_ref.self_ty();
+ if let ty::Param(_) = ty.kind() {
+ bounds.push((
+ format!("{ty}"),
+ trait_ref.print_only_trait_path().to_string(),
+ Some(trait_ref.def_id),
+ ));
+ }
+ }
+ }
+ }
+ InfringingFieldsReason::Regions(region_errors) => {
+ for error in region_errors {
+ let ty = ty.to_string();
+ match error {
+ RegionResolutionError::ConcreteFailure(origin, a, b) => {
+ let predicate = format!("{b}: {a}");
+ errors
+ .entry((ty.clone(), predicate.clone()))
+ .or_default()
+ .push(origin.span());
+ if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
+ bounds.push((b.to_string(), a.to_string(), None));
+ }
+ }
+ RegionResolutionError::GenericBoundFailure(origin, a, b) => {
+ let predicate = format!("{a}: {b}");
+ errors
+ .entry((ty.clone(), predicate.clone()))
+ .or_default()
+ .push(origin.span());
+ if let infer::region_constraints::GenericKind::Param(_) = a {
+ bounds.push((a.to_string(), b.to_string(), None));
+ }
+ }
+ _ => continue,
+ }
+ }
+ }
+ }
+ }
+ for ((ty, error_predicate), spans) in errors {
+ let span: MultiSpan = spans.into();
+ err.span_note(
+ span,
+ format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"),
+ );
+ }
+ suggest_constraining_type_params(
+ tcx,
+ tcx.hir().get_generics(impl_did).expect("impls always have generics"),
+ &mut err,
+ bounds
+ .iter()
+ .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
+ None,
+ );
+
+ err.emit()
+}
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 3d37e0ce0..335590206 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -146,7 +146,7 @@ impl<'tcx> InherentCollect<'tcx> {
);
err.help("consider using an extension trait instead");
if let ty::Ref(_, subty, _) = ty.kind() {
- err.note(&format!(
+ err.note(format!(
"you could also try moving the reference to \
uses of `{}` (such as `self`) within the implementation",
subty
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index ad76e2bed..bd6252344 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -3,7 +3,7 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Symbol;
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 465e787c9..4524b87a4 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -5,9 +5,10 @@
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.
+use crate::errors;
use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
use rustc_trait_selection::traits;
@@ -22,7 +23,7 @@ fn check_impl(tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_ref: ty::TraitRef<
debug!(
"(checking implementation) adding impl for trait '{:?}', item '{}'",
trait_ref,
- tcx.def_path_str(impl_def_id.to_def_id())
+ tcx.def_path_str(impl_def_id)
);
// Skip impls where one of the self type is an error type.
@@ -67,13 +68,7 @@ fn enforce_trait_manually_implementable(
tcx.trait_def(trait_def_id).specialization_kind
{
if !tcx.features().specialization && !tcx.features().min_specialization {
- tcx.sess
- .struct_span_err(
- impl_header_span,
- "implementing `rustc_specialization_trait` traits is unstable",
- )
- .help("add `#![feature(min_specialization)]` to the crate attributes to enable")
- .emit();
+ tcx.sess.emit_err(errors::SpecializationTrait { span: impl_header_span });
return;
}
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 47c47de8c..23beacd2a 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, DelayDm};
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::util::IgnoreRegions;
+use rustc_middle::ty::util::CheckRegions;
use rustc_middle::ty::{
self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor,
@@ -210,6 +210,19 @@ fn do_orphan_check_impl<'tcx>(
NonlocalImpl::DisallowOther,
),
+ // ```
+ // struct S<T>(T);
+ // impl<T: ?Sized> S<T> {
+ // type This = T;
+ // }
+ // impl<T: ?Sized> AutoTrait for S<T>::This {}
+ // ```
+ // FIXME(inherent_associated_types): The example code above currently leads to a cycle
+ ty::Alias(AliasKind::Inherent, _) => (
+ LocalImpl::Disallow { problematic_kind: "associated type" },
+ NonlocalImpl::DisallowOther,
+ ),
+
// type Opaque = impl Trait;
// impl AutoTrait for Opaque {}
ty::Alias(AliasKind::Opaque, _) => (
@@ -372,10 +385,10 @@ fn emit_orphan_check_error<'tcx>(
if is_target_ty {
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
- err.span_label(self_ty_span, &msg);
+ err.span_label(self_ty_span, msg);
} else {
// Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
- err.span_label(trait_span, &msg);
+ err.span_label(trait_span, msg);
}
}
err.note("define and implement a trait or new type instead");
@@ -457,7 +470,7 @@ fn emit_newtype_suggestion_for_raw_ptr(
ptr_ty: &ty::TypeAndMut<'_>,
diag: &mut Diagnostic,
) {
- if !self_ty.needs_subst() {
+ if !self_ty.has_param() {
let mut_key = ptr_ty.mutbl.prefix_str();
let msg_sugg = "consider introducing a new wrapper type".to_owned();
let sugg = vec![
@@ -494,7 +507,7 @@ fn lint_auto_trait_impl<'tcx>(
// Impls which completely cover a given root type are fine as they
// disable auto impls entirely. So only lint if the substs
// are not a permutation of the identity substs.
- let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else {
+ let Err(arg) = tcx.uses_unique_generic_params(substs, CheckRegions::No) else {
// ok
return;
};
@@ -531,15 +544,15 @@ fn lint_auto_trait_impl<'tcx>(
let self_descr = tcx.def_descr(self_type_did);
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
- lint.note(&format!("`{}` is mentioned multiple times", arg));
+ lint.note(format!("`{}` is mentioned multiple times", arg));
}
ty::util::NotUniqueParam::NotParam(arg) => {
- lint.note(&format!("`{}` is not a generic parameter", arg));
+ lint.note(format!("`{}` is not a generic parameter", arg));
}
}
lint.span_note(
item_span,
- &format!(
+ format!(
"try using the same sequence of generic parameters as the {} definition",
self_descr,
),
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index cbbaf8f85..ca0d5509c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -28,7 +28,7 @@ use rustc_hir::{GenericParamKind, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -55,7 +55,6 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
pub fn provide(providers: &mut Providers) {
resolve_bound_vars::provide(providers);
*providers = Providers {
- opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,
@@ -65,8 +64,8 @@ pub fn provide(providers: &mut Providers) {
explicit_predicates_of: predicates_of::explicit_predicates_of,
super_predicates_of: predicates_of::super_predicates_of,
implied_predicates_of: predicates_of::implied_predicates_of,
- super_predicates_that_define_assoc_type:
- predicates_of::super_predicates_that_define_assoc_type,
+ super_predicates_that_define_assoc_item:
+ predicates_of::super_predicates_that_define_assoc_item,
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
type_param_predicates: predicates_of::type_param_predicates,
trait_def,
@@ -74,7 +73,6 @@ pub fn provide(providers: &mut Providers) {
fn_sig,
impl_trait_ref,
impl_polarity,
- is_foreign_item,
generator_kind,
collect_mod_item_types,
is_type_alias_impl_trait,
@@ -387,8 +385,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
- ty::ReErased => self.tcx.lifetimes.re_static,
- _ => r,
+ // This is never reached in practice. If it ever is reached,
+ // `ReErased` should be changed to `ReStatic`, and any other region
+ // left alone.
+ r => bug!("unexpected region: {r:?}"),
});
self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
}
@@ -819,7 +819,7 @@ fn convert_variant(
recovered,
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|| variant_did
- .map_or(false, |variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
+ .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
)
}
@@ -1025,7 +1025,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
}
Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
- ty_opt.map_or(false, is_suggestable_infer_ty)
+ ty_opt.is_some_and(is_suggestable_infer_ty)
|| segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
}
_ => false,
@@ -1147,8 +1147,14 @@ fn infer_return_ty_for_fn_sig<'tcx>(
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_ty(ty);
+
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.output();
+ // Don't leak types into signatures unless they're nameable!
+ // For example, if a function returns itself, we don't want that
+ // recursive function definition to leak out into the fn sig.
+ let mut should_recover = false;
+
if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
diag.span_suggestion(
ty.span,
@@ -1156,15 +1162,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
ret_ty,
Applicability::MachineApplicable,
);
- } else if matches!(ret_ty.kind(), ty::FnDef(..))
- && let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false)
- {
- diag.span_suggestion(
- ty.span,
- "replace with the correct return type",
- fn_sig,
- Applicability::MachineApplicable,
- );
+ should_recover = true;
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) {
diag.span_suggestion(
ty.span,
@@ -1182,9 +1180,20 @@ fn infer_return_ty_for_fn_sig<'tcx>(
https://doc.rust-lang.org/book/ch13-01-closures.html",
);
}
- diag.emit();
- ty::Binder::dummy(fn_sig)
+ let guar = diag.emit();
+
+ if should_recover {
+ ty::Binder::dummy(fn_sig)
+ } else {
+ ty::Binder::dummy(tcx.mk_fn_sig(
+ fn_sig.inputs().iter().copied(),
+ tcx.ty_error(guar),
+ fn_sig.c_variadic,
+ fn_sig.unsafety,
+ fn_sig.abi,
+ ))
+ }
}
None => icx.astconv().ty_of_fn(
hir_id,
@@ -1456,13 +1465,6 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
fty
}
-fn is_foreign_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- match tcx.hir().get_by_def_id(def_id) {
- Node::ForeignItem(..) => true,
- _ => false,
- }
-}
-
fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
match tcx.hir().get_by_def_id(def_id) {
Node::Expr(&rustc_hir::Expr {
@@ -1476,7 +1478,7 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorK
fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
match tcx.hir().get_by_def_id(def_id) {
Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => {
- matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)
+ matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
}
_ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
}
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 119933697..ed60998ec 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -51,7 +51,15 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
None
} else if tcx.lazy_normalization() {
- if let Some(param_id) = tcx.hir().opt_const_param_default_param_def_id(hir_id) {
+ let parent_node = tcx.hir().get_parent(hir_id);
+ if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
+ && constant.hir_id == hir_id
+ {
+ // enum variant discriminants are not allowed to use any kind of generics
+ None
+ } else if let Some(param_id) =
+ tcx.hir().opt_const_param_default_param_def_id(hir_id)
+ {
// If the def_id we are calling generics_of on is an anon ct default i.e:
//
// struct Foo<const N: usize = { .. }>;
@@ -94,15 +102,15 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
has_self: generics.has_self,
has_late_bound_regions: generics.has_late_bound_regions,
};
+ } else {
+ // HACK(eddyb) this provides the correct generics when
+ // `feature(generic_const_expressions)` is enabled, so that const expressions
+ // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
+ //
+ // Note that we do not supply the parent generics when using
+ // `min_const_generics`.
+ Some(parent_def_id.to_def_id())
}
-
- // HACK(eddyb) this provides the correct generics when
- // `feature(generic_const_expressions)` is enabled, so that const expressions
- // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
- //
- // Note that we do not supply the parent generics when using
- // `min_const_generics`.
- Some(parent_def_id.to_def_id())
} else {
let parent_node = tcx.hir().get_parent(hir_id);
match parent_node {
@@ -115,11 +123,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
{
Some(parent_def_id.to_def_id())
}
- Node::Variant(Variant { disr_expr: Some(constant), .. })
- if constant.hir_id == hir_id =>
- {
- Some(parent_def_id.to_def_id())
- }
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
}
@@ -156,7 +159,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
Some(fn_def_id.to_def_id())
}
- ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+ ItemKind::OpaqueTy(hir::OpaqueTy {
+ origin: hir::OpaqueTyOrigin::TyAlias { .. },
+ ..
+ }) => {
let parent_id = tcx.hir().get_parent_item(hir_id);
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 2e56d2463..948b903e5 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -1,5 +1,5 @@
use super::ItemCtxt;
-use crate::astconv::AstConv;
+use crate::astconv::{AstConv, OnlySelfBounds};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
@@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>(
);
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
- let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
@@ -67,7 +67,7 @@ fn opaque_type_bounds<'tcx>(
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
ty::print::with_no_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
- let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
// Opaque types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds);
@@ -79,14 +79,14 @@ fn opaque_type_bounds<'tcx>(
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> &'_ [(ty::Predicate<'_>, Span)] {
+) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
match tcx.opt_rpitit_info(def_id.to_def_id()) {
// RPITIT's bounds are the same as opaque type bounds, but with
// a projection self type.
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
let opaque_ty = item.expect_opaque_ty();
- return opaque_type_bounds(
+ return ty::EarlyBinder(opaque_type_bounds(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
@@ -95,7 +95,7 @@ pub(super) fn explicit_item_bounds(
ty::InternalSubsts::identity_for_item(tcx, def_id),
),
item.span,
- );
+ ));
}
// These should have been fed!
Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
@@ -103,7 +103,7 @@ pub(super) fn explicit_item_bounds(
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- match tcx.hir().get(hir_id) {
+ let bounds = match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _),
span,
@@ -123,16 +123,18 @@ pub(super) fn explicit_item_bounds(
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
_ => bug!("item_bounds called on {:?}", def_id),
- }
+ };
+ ty::EarlyBinder(bounds)
}
pub(super) fn item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
- let bounds = tcx.mk_predicates_from_iter(util::elaborate(
- tcx,
- tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
- ));
- ty::EarlyBinder(bounds)
+ tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
+ tcx.mk_predicates_from_iter(util::elaborate(
+ tcx,
+ bounds.iter().map(|&(bound, _span)| bound),
+ ))
+ })
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 9358ed612..e5b5dae55 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,4 +1,4 @@
-use crate::astconv::AstConv;
+use crate::astconv::{AstConv, OnlySelfBounds};
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
@@ -14,9 +14,6 @@ use rustc_middle::ty::{GenericPredicates, ToPredicate};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
-#[derive(Debug)]
-struct OnlySelfBounds(bool);
-
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
/// `Self: Trait` predicates for traits.
@@ -99,8 +96,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
| ItemKind::Struct(_, generics)
| ItemKind::Union(_, generics) => generics,
- ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id()));
+ ItemKind::Trait(_, _, generics, self_bounds, ..)
+ | ItemKind::TraitAlias(generics, self_bounds) => {
+ is_trait = Some(self_bounds);
generics
}
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
@@ -122,10 +120,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// Below we'll consider the bounds on the type parameters (including `Self`)
// and the explicit where-clauses, but to get the full set of predicates
- // on a trait we need to add in the supertrait bounds and bounds found on
- // associated types.
- if let Some(_trait_ref) = is_trait {
- predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
+ // on a trait we must also consider the bounds that follow the trait's name,
+ // like `trait Foo: A + B + C`.
+ if let Some(self_bounds) = is_trait {
+ predicates.extend(
+ icx.astconv()
+ .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
+ .predicates(),
+ );
}
// In default impls, we can assume that the self type implements
@@ -225,7 +227,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
let mut bounds = Bounds::default();
- icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
+ icx.astconv().add_bounds(
+ ty,
+ bound_pred.bounds.iter(),
+ &mut bounds,
+ bound_vars,
+ OnlySelfBounds(false),
+ );
predicates.extend(bounds.predicates());
}
@@ -419,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
// supertrait).
if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.substs == trait_identity_substs
+ // FIXME(return_type_notation): This check should be more robust
+ && !tcx.is_impl_trait_in_trait(projection.def_id)
&& tcx.associated_item(projection.def_id).container_id(tcx)
== def_id.to_def_id()
} else {
@@ -557,7 +567,7 @@ pub(super) fn super_predicates_of(
implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
}
-pub(super) fn super_predicates_that_define_assoc_type(
+pub(super) fn super_predicates_that_define_assoc_item(
tcx: TyCtxt<'_>,
(trait_def_id, assoc_name): (DefId, Ident),
) -> ty::GenericPredicates<'_> {
@@ -608,7 +618,7 @@ pub(super) fn implied_predicates_with_filter(
let (superbounds, where_bounds_that_match) = match filter {
PredicateFilter::All => (
// Convert the bounds that follow the colon (or equal in trait aliases)
- icx.astconv().compute_bounds(self_param_ty, bounds),
+ icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
// Also include all where clause bounds
icx.type_parameter_bounds_in_generics(
generics,
@@ -620,7 +630,7 @@ pub(super) fn implied_predicates_with_filter(
),
PredicateFilter::SelfOnly => (
// Convert the bounds that follow the colon (or equal in trait aliases)
- icx.astconv().compute_bounds(self_param_ty, bounds),
+ icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
// Include where clause bounds for `Self`
icx.type_parameter_bounds_in_generics(
generics,
@@ -632,7 +642,7 @@ pub(super) fn implied_predicates_with_filter(
),
PredicateFilter::SelfThatDefines(assoc_name) => (
// Convert the bounds that follow the colon (or equal) that reference the associated name
- icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
+ icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name),
// Include where clause bounds for `Self` that reference the associated name
icx.type_parameter_bounds_in_generics(
generics,
@@ -645,19 +655,19 @@ pub(super) fn implied_predicates_with_filter(
};
// Combine the two lists to form the complete set of superbounds:
- let implied_bounds = &*tcx
- .arena
- .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
+ let implied_bounds =
+ &*tcx.arena.alloc_from_iter(superbounds.predicates().chain(where_bounds_that_match));
debug!(?implied_bounds);
- // Now require that immediate supertraits are converted,
- // which will, in turn, reach indirect supertraits.
+ // Now require that immediate supertraits are converted, which will, in
+ // turn, reach indirect supertraits, so we detect cycles now instead of
+ // overflowing during elaboration.
if matches!(filter, PredicateFilter::SelfOnly) {
- // Now require that immediate supertraits are converted,
- // which will, in turn, reach indirect supertraits.
for &(pred, span) in implied_bounds {
debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder()
+ && bound.polarity == ty::ImplPolarity::Positive
+ {
tcx.at(span).super_predicates_of(bound.def_id());
}
}
@@ -713,7 +723,7 @@ pub(super) fn type_param_predicates(
| ItemKind::TyAlias(_, generics)
| ItemKind::OpaqueTy(OpaqueTy {
generics,
- origin: hir::OpaqueTyOrigin::TyAlias,
+ origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
})
| ItemKind::Enum(_, generics)
@@ -775,32 +785,35 @@ impl<'tcx> ItemCtxt<'tcx> {
only_self_bounds: OnlySelfBounds,
assoc_name: Option<Ident>,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
- ast_generics
- .predicates
- .iter()
- .filter_map(|wp| match wp {
- hir::WherePredicate::BoundPredicate(bp) => Some(bp),
- _ => None,
- })
- .flat_map(|bp| {
- let bt = if bp.is_param_bound(param_def_id.to_def_id()) {
- Some(ty)
- } else if !only_self_bounds.0 {
- Some(self.to_ty(bp.bounded_ty))
- } else {
- None
- };
- let bvars = self.tcx.late_bound_vars(bp.hir_id);
-
- bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
- |(_, b, _)| match assoc_name {
- Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
- None => true,
- },
- )
- })
- .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
- .collect()
+ let mut bounds = Bounds::default();
+
+ for predicate in ast_generics.predicates {
+ let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
+ continue;
+ };
+
+ let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
+ ty
+ } else if !only_self_bounds.0 {
+ self.to_ty(predicate.bounded_ty)
+ } else {
+ continue;
+ };
+
+ let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
+ self.astconv().add_bounds(
+ bound_ty,
+ predicate.bounds.iter().filter(|bound| {
+ assoc_name
+ .map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
+ }),
+ &mut bounds,
+ bound_vars,
+ only_self_bounds,
+ );
+ }
+
+ bounds.predicates().collect()
}
#[instrument(level = "trace", skip(self))]
@@ -809,7 +822,7 @@ impl<'tcx> ItemCtxt<'tcx> {
hir::GenericBound::Trait(poly_trait_ref, _) => {
let trait_ref = &poly_trait_ref.trait_ref;
if let Some(trait_did) = trait_ref.trait_def_id() {
- self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
+ self.tcx.trait_may_define_assoc_item(trait_did, assoc_name)
} else {
false
}
@@ -818,19 +831,3 @@ impl<'tcx> ItemCtxt<'tcx> {
}
}
}
-
-/// Converts a specific `GenericBound` from the AST into a set of
-/// predicates that apply to the self type. A vector is returned
-/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
-/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar`
-/// and `<T as Bar>::X == i32`).
-fn predicates_from_bound<'tcx>(
- astconv: &dyn AstConv<'tcx>,
- param_ty: Ty<'tcx>,
- bound: &'tcx hir::GenericBound<'tcx>,
- bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
- let mut bounds = Bounds::default();
- astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
- bounds.predicates().collect()
-}
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index e758fe95d..794812a5c 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -17,6 +17,7 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::*;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::def_id::DefId;
@@ -232,8 +233,8 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
type ScopeRef<'a> = &'a Scope<'a>;
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers {
resolve_bound_vars,
named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
@@ -455,13 +456,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
.collect::<Vec<_>>();
if !infer_spans.is_empty() {
- self.tcx.sess
- .struct_span_err(
- infer_spans,
- "implicit types in closure signatures are forbidden when `for<...>` is present",
- )
- .span_label(for_sp, "`for<...>` is here")
- .emit();
+ self.tcx
+ .sess
+ .emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
}
}
@@ -530,7 +527,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
});
}
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- origin: hir::OpaqueTyOrigin::TyAlias, ..
+ origin: hir::OpaqueTyOrigin::TyAlias { .. },
+ ..
}) => {
// Opaque types are visited when we visit the
// `TyKind::OpaqueDef`, so that they have the lifetimes from
@@ -711,7 +709,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let opaque_ty = self.tcx.hir().item(item_id);
match &opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- origin: hir::OpaqueTyOrigin::TyAlias,
+ origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
}) => {
intravisit::walk_ty(self, ty);
@@ -991,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
lifetime.ident
),
|lint| {
- let help = &format!(
+ let help = format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.ident,
);
@@ -1333,7 +1331,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
// AST-based resolution does not care for impl-trait desugaring, which are the
- // responibility of lowering. This may create a mismatch between the resolution
+ // responsibility of lowering. This may create a mismatch between the resolution
// AST found (`region_def_id`) which points to HRTB, and what HIR allows.
// ```
// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
@@ -1369,7 +1367,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
self.tcx.sess.delay_span_bug(
lifetime_ref.ident.span,
- &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
+ format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
);
}
@@ -1656,17 +1654,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
let bound_vars = if let Some(type_def_id) = type_def_id
&& self.tcx.def_kind(type_def_id) == DefKind::Trait
- // FIXME(return_type_notation): We could bound supertrait methods.
- && let Some(assoc_fn) = self
- .tcx
- .associated_items(type_def_id)
- .find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
+ && let Some((mut bound_vars, assoc_fn)) =
+ BoundVarContext::supertrait_hrtb_vars(
+ self.tcx,
+ type_def_id,
+ binding.ident,
+ ty::AssocKind::Fn,
+ )
{
- self.tcx
- .generics_of(assoc_fn.def_id)
- .params
- .iter()
- .map(|param| match param.kind {
+ bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).params.iter().map(
+ |param| match param.kind {
ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
ty::BoundRegionKind::BrNamed(param.def_id, param.name),
),
@@ -1674,9 +1671,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
ty::BoundTyKind::Param(param.def_id, param.name),
),
ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
- })
- .chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars())
- .collect()
+ },
+ ));
+ bound_vars
+ .extend(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars());
+ bound_vars
} else {
self.tcx.sess.delay_span_bug(
binding.ident.span,
@@ -1693,8 +1692,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
});
});
} else if let Some(type_def_id) = type_def_id {
- let bound_vars =
- BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
+ let bound_vars = BoundVarContext::supertrait_hrtb_vars(
+ self.tcx,
+ type_def_id,
+ binding.ident,
+ ty::AssocKind::Type,
+ )
+ .map(|(bound_vars, _)| bound_vars);
self.with(scope, |this| {
let scope = Scope::Supertrait {
bound_vars: bound_vars.unwrap_or_default(),
@@ -1724,11 +1728,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
def_id: DefId,
assoc_name: Ident,
- ) -> Option<Vec<ty::BoundVariableKind>> {
- let trait_defines_associated_type_named = |trait_def_id: DefId| {
- tcx.associated_items(trait_def_id)
- .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
- .is_some()
+ assoc_kind: ty::AssocKind,
+ ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
+ let trait_defines_associated_item_named = |trait_def_id: DefId| {
+ tcx.associated_items(trait_def_id).find_by_name_and_kind(
+ tcx,
+ assoc_name,
+ assoc_kind,
+ trait_def_id,
+ )
};
use smallvec::{smallvec, SmallVec};
@@ -1746,10 +1754,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
_ => break None,
}
- if trait_defines_associated_type_named(def_id) {
- break Some(bound_vars.into_iter().collect());
+ if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
+ break Some((bound_vars.into_iter().collect(), assoc_item));
}
- let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
+ let predicates = tcx.super_predicates_that_define_assoc_item((def_id, assoc_name));
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
@@ -1917,7 +1925,7 @@ fn is_late_bound_map(
/// handles cycle detection as we go through the query system.
///
/// This is necessary in the first place for the following case:
- /// ```
+ /// ```rust,ignore (pseudo-Rust)
/// type Alias<'a, T> = <T as Trait<'a>>::Assoc;
/// fn foo<'a>(_: Alias<'a, ()>) -> Alias<'a, ()> { ... }
/// ```
@@ -1942,7 +1950,7 @@ fn is_late_bound_map(
ty::Param(param_ty) => {
self.arg_is_constrained[param_ty.index as usize] = true;
}
- ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
+ ty::Alias(ty::Projection | ty::Inherent, _) => return ControlFlow::Continue(()),
_ => (),
}
t.super_visit_with(self)
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c173bd913..8e082d3c5 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -1,10 +1,7 @@
use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{HirId, Node};
-use rustc_middle::hir::nested_filter;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::HirId;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
@@ -14,24 +11,84 @@ use rustc_span::{Span, DUMMY_SP};
use super::ItemCtxt;
use super::{bad_placeholder, is_suggestable_infer_ty};
-use crate::errors::UnconstrainedOpaqueType;
-/// Computes the relevant generic parameter for a potential generic const argument.
-///
-/// This should be called using the query `tcx.opt_const_param_of`.
-pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
+mod opaque;
+
+fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
use hir::*;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- match tcx.hir().get(hir_id) {
- Node::AnonConst(_) => (),
- _ => return None,
- };
+ let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() };
let parent_node_id = tcx.hir().parent_id(hir_id);
let parent_node = tcx.hir().get(parent_node_id);
let (generics, arg_idx) = match parent_node {
+ // Easy case: arrays repeat expressions.
+ Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
+ | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+ if constant.hir_id() == hir_id =>
+ {
+ return tcx.types.usize
+ }
+ Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
+ return tcx.typeck(def_id).node_type(e.hir_id)
+ }
+ Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
+ if anon_const.hir_id == hir_id =>
+ {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ return substs.as_inline_const().ty()
+ }
+ Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
+ | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
+ if asm.operands.iter().any(|(op, _op_sp)| match op {
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
+ _ => false,
+ }) =>
+ {
+ return tcx.typeck(def_id).node_type(hir_id)
+ }
+ Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
+ return tcx
+ .adt_def(tcx.hir().get_parent_item(hir_id))
+ .repr()
+ .discr_type()
+ .to_ty(tcx)
+ }
+ Node::GenericParam(&GenericParam {
+ def_id: param_def_id,
+ kind: GenericParamKind::Const { default: Some(ct), .. },
+ ..
+ }) if ct.hir_id == hir_id => {
+ return tcx.type_of(param_def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic")
+ }
+
+ Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
+ if let Node::TraitRef(trait_ref) = tcx.hir().get(
+ tcx.hir().parent_id(binding_id)
+ ) =>
+ {
+ let Some(trait_def_id) = trait_ref.trait_def_id() else {
+ return tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find trait");
+ };
+ let assoc_items = tcx.associated_items(trait_def_id);
+ let assoc_item = assoc_items.find_by_name_and_kind(
+ tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
+ );
+ return if let Some(assoc_item) = assoc_item {
+ tcx.type_of(assoc_item.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic")
+ } else {
+ // FIXME(associated_const_equality): add a useful error message here.
+ tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find associated const on trait")
+ }
+ }
+
// This match arm is for when the def_id appears in a GAT whose
// path can't be resolved without typechecking e.g.
//
@@ -68,7 +125,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// the def_id that this query was called with. We filter to only type and const args here
// as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
// but it can't hurt to be safe ^^
- if let ty::Alias(ty::Projection, projection) = ty.kind() {
+ if let ty::Alias(ty::Projection | ty::Inherent, projection) = ty.kind() {
let generics = tcx.generics_of(projection.def_id);
let arg_index = segment
@@ -86,11 +143,10 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
- return None;
}
}
Node::Expr(&Expr {
@@ -103,7 +159,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// This may fail in case the method/path does not actually exist.
// As there is no relevant param for `def_id`, we simply return
// `None` here.
- let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
+ let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
+ return tcx.ty_error_with_message(
+ tcx.def_span(def_id),
+ format!("unable to find type-dependent def for {:?}", parent_node_id),
+ );
+ };
let idx = segment
.args
.and_then(|args| {
@@ -140,19 +201,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
- &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
+ format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
);
- return None;
}
}
_ => {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
- &format!("unexpected const parent path {:?}", parent_node),
+ format!("unexpected const parent path {:?}", parent_node),
);
- return None;
}
};
@@ -171,32 +230,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg)))
}) else {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
"no arg matching AnonConst in path",
);
- return None;
};
let generics = match tcx.res_generics_def_id(segment.res) {
Some(def_id) => tcx.generics_of(def_id),
None => {
- tcx.sess.delay_span_bug(
+ return tcx.ty_error_with_message(
tcx.def_span(def_id),
- &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
+ format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
);
- return None;
}
};
(generics, arg_index)
}
- _ => return None,
+
+ _ => return tcx.ty_error_with_message(
+ tcx.def_span(def_id),
+ format!("unexpected const parent in type_of(): {parent_node:?}"),
+ ),
};
debug!(?parent_node);
debug!(?generics, ?arg_idx);
- generics
+ if let Some(param_def_id) = generics
.params
.iter()
.filter(|param| param.kind.is_ty_or_const())
@@ -211,6 +272,14 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
}
_ => None,
})
+ {
+ tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
+ } else {
+ return tcx.ty_error_with_message(
+ tcx.def_span(def_id),
+ format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
+ );
+ }
}
fn get_path_containing_arg_in_pat<'hir>(
@@ -251,7 +320,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
- return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]);
+ return map[&assoc_item.trait_item_def_id.unwrap()];
}
Err(_) => {
return ty::EarlyBinder(tcx.ty_error_with_message(
@@ -355,9 +424,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_adt(def, substs)
}
- ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
- find_opaque_ty_constraints_for_tait(tcx, def_id)
- }
+ ItemKind::OpaqueTy(OpaqueTy {
+ origin: hir::OpaqueTyOrigin::TyAlias { .. },
+ ..
+ }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
// Opaque types desugared from `impl Trait`.
ItemKind::OpaqueTy(OpaqueTy {
origin:
@@ -371,7 +441,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
"tried to get type of this RPITIT with no definition"
);
}
- find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+ opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
}
ItemKind::Trait(..)
| ItemKind::TraitAlias(..)
@@ -415,143 +485,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
tcx.typeck(def_id).node_type(hir_id)
}
- Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
- // We defer to `type_of` of the corresponding parameter
- // for generic arguments.
- tcx.type_of(param).subst_identity()
- }
-
- Node::AnonConst(_) => {
- let parent_node = tcx.hir().get_parent(hir_id);
- match parent_node {
- Node::Ty(Ty { kind: TyKind::Array(_, constant), .. })
- | Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
- if constant.hir_id() == hir_id =>
- {
- tcx.types.usize
- }
- Node::Ty(Ty { kind: TyKind::Typeof(e), .. }) if e.hir_id == hir_id => {
- tcx.typeck(def_id).node_type(e.hir_id)
- }
-
- Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. })
- if anon_const.hir_id == hir_id =>
- {
- let substs = InternalSubsts::identity_for_item(tcx, def_id);
- substs.as_inline_const().ty()
- }
-
- Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
- | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
- if asm.operands.iter().any(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const }
- | hir::InlineAsmOperand::SymFn { anon_const } => {
- anon_const.hir_id == hir_id
- }
- _ => false,
- }) =>
- {
- tcx.typeck(def_id).node_type(hir_id)
- }
-
- Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
- tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
- }
-
- Node::TypeBinding(TypeBinding {
- hir_id: binding_id,
- kind: TypeBindingKind::Equality { term: Term::Const(e) },
- ident,
- ..
- }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id)
- && e.hir_id == hir_id =>
- {
- let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
- };
- let assoc_items = tcx.associated_items(trait_def_id);
- let assoc_item = assoc_items.find_by_name_and_kind(
- tcx,
- *ident,
- ty::AssocKind::Const,
- def_id.to_def_id(),
- );
- if let Some(assoc_item) = assoc_item {
- tcx.type_of(assoc_item.def_id)
- .no_bound_vars()
- .expect("const parameter types cannot be generic")
- } else {
- // FIXME(associated_const_equality): add a useful error message here.
- tcx.ty_error_with_message(
- DUMMY_SP,
- "Could not find associated const on trait",
- )
- }
- }
-
- Node::TypeBinding(TypeBinding {
- hir_id: binding_id,
- gen_args,
- kind,
- ident,
- ..
- }) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id)
- && let Some((idx, _)) =
- gen_args.args.iter().enumerate().find(|(_, arg)| {
- if let GenericArg::Const(ct) = arg {
- ct.value.hir_id == hir_id
- } else {
- false
- }
- }) =>
- {
- let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
- };
- let assoc_items = tcx.associated_items(trait_def_id);
- let assoc_item = assoc_items.find_by_name_and_kind(
- tcx,
- *ident,
- match kind {
- // I think `<A: T>` type bindings requires that `A` is a type
- TypeBindingKind::Constraint { .. }
- | TypeBindingKind::Equality { term: Term::Ty(..) } => {
- ty::AssocKind::Type
- }
- TypeBindingKind::Equality { term: Term::Const(..) } => {
- ty::AssocKind::Const
- }
- },
- def_id.to_def_id(),
- );
- if let Some(assoc_item) = assoc_item
- && let param = &tcx.generics_of(assoc_item.def_id).params[idx]
- && matches!(param.kind, ty::GenericParamDefKind::Const { .. })
- {
- tcx.type_of(param.def_id)
- .no_bound_vars()
- .expect("const parameter types cannot be generic")
- } else {
- // FIXME(associated_const_equality): add a useful error message here.
- tcx.ty_error_with_message(
- DUMMY_SP,
- "Could not find const param on associated item",
- )
- }
- }
-
- Node::GenericParam(&GenericParam {
- def_id: param_def_id,
- kind: GenericParamKind::Const { default: Some(ct), .. },
- ..
- }) if ct.hir_id == hir_id => tcx.type_of(param_def_id).subst_identity(),
-
- x => tcx.ty_error_with_message(
- DUMMY_SP,
- &format!("unexpected const parent in type_of(): {x:?}"),
- ),
- }
- }
+ Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
Node::GenericParam(param) => match &param.kind {
GenericParamKind::Type { default: Some(ty), .. }
@@ -566,303 +500,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
ty::EarlyBinder(output)
}
-#[instrument(skip(tcx), level = "debug")]
-/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
-/// laid for "higher-order pattern unification".
-/// This ensures that inference is tractable.
-/// In particular, definitions of opaque types can only use other generics as arguments,
-/// and they cannot repeat an argument. Example:
-///
-/// ```ignore (illustrative)
-/// type Foo<A, B> = impl Bar<A, B>;
-///
-/// // Okay -- `Foo` is applied to two distinct, generic types.
-/// fn a<T, U>() -> Foo<T, U> { .. }
-///
-/// // Not okay -- `Foo` is applied to `T` twice.
-/// fn b<T>() -> Foo<T, T> { .. }
-///
-/// // Not okay -- `Foo` is applied to a non-generic type.
-/// fn b<T>() -> Foo<T, u32> { .. }
-/// ```
-///
-fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
- use rustc_hir::{Expr, ImplItem, Item, TraitItem};
-
- struct ConstraintLocator<'tcx> {
- tcx: TyCtxt<'tcx>,
-
- /// def_id of the opaque type whose defining uses are being checked
- def_id: LocalDefId,
-
- /// as we walk the defining uses, we are checking that all of them
- /// define the same hidden type. This variable is set to `Some`
- /// with the first type that we find, and then later types are
- /// checked against it (we also carry the span of that first
- /// type).
- found: Option<ty::OpaqueHiddenType<'tcx>>,
-
- /// In the presence of dead code, typeck may figure out a hidden type
- /// while borrowck will not. We collect these cases here and check at
- /// the end that we actually found a type that matches (modulo regions).
- typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
- }
-
- impl ConstraintLocator<'_> {
- #[instrument(skip(self), level = "debug")]
- fn check(&mut self, item_def_id: LocalDefId) {
- // Don't try to check items that cannot possibly constrain the type.
- if !self.tcx.has_typeck_results(item_def_id) {
- debug!("no constraint: no typeck results");
- return;
- }
- // Calling `mir_borrowck` can lead to cycle errors through
- // const-checking, avoid calling it if we don't have to.
- // ```rust
- // type Foo = impl Fn() -> usize; // when computing type for this
- // const fn bar() -> Foo {
- // || 0usize
- // }
- // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
- // // because we again need to reveal `Foo` so we can check whether the
- // // constant does not contain interior mutability.
- // ```
- let tables = self.tcx.typeck(item_def_id);
- if let Some(guar) = tables.tainted_by_errors {
- self.found =
- Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
- return;
- }
- let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
- debug!("no constraints in typeck results");
- return;
- };
- if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
- self.typeck_types.push(typeck_hidden_ty);
- }
-
- // Use borrowck to get the type with unerased regions.
- let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
- debug!(?concrete_opaque_types);
- if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
- debug!(?concrete_type, "found constraint");
- if let Some(prev) = &mut self.found {
- if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
- let guar = prev.report_mismatch(&concrete_type, self.tcx);
- prev.ty = self.tcx.ty_error(guar);
- }
- } else {
- self.found = Some(concrete_type);
- }
- }
- }
- }
-
- impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
- fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
- if let hir::ExprKind::Closure(closure) = ex.kind {
- self.check(closure.def_id);
- }
- intravisit::walk_expr(self, ex);
- }
- fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_item(self, it);
- }
- }
- fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_impl_item(self, it);
- }
- }
- fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
- trace!(?it.owner_id);
- self.check(it.owner_id.def_id);
- intravisit::walk_trait_item(self, it);
- }
- }
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let scope = tcx.hir().get_defining_scope(hir_id);
- let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
-
- debug!(?scope);
-
- if scope == hir::CRATE_HIR_ID {
- tcx.hir().walk_toplevel_module(&mut locator);
- } else {
- trace!("scope={:#?}", tcx.hir().get(scope));
- match tcx.hir().get(scope) {
- // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
- // This allows our visitor to process the defining item itself, causing
- // it to pick up any 'sibling' defining uses.
- //
- // For example, this code:
- // ```
- // fn foo() {
- // type Blah = impl Debug;
- // let my_closure = || -> Blah { true };
- // }
- // ```
- //
- // requires us to explicitly process `foo()` in order
- // to notice the defining usage of `Blah`.
- Node::Item(it) => locator.visit_item(it),
- Node::ImplItem(it) => locator.visit_impl_item(it),
- Node::TraitItem(it) => locator.visit_trait_item(it),
- other => bug!("{:?} is not a valid scope for an opaque type item", other),
- }
- }
-
- let Some(hidden) = locator.found else {
- let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
- span: tcx.def_span(def_id),
- name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
- what: match tcx.hir().get(scope) {
- _ if scope == hir::CRATE_HIR_ID => "module",
- Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
- Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
- _ => "item",
- },
- });
- return tcx.ty_error(reported);
- };
-
- // Only check against typeck if we didn't already error
- if !hidden.ty.references_error() {
- for concrete_type in locator.typeck_types {
- if tcx.erase_regions(concrete_type.ty) != tcx.erase_regions(hidden.ty)
- && !(concrete_type, hidden).references_error()
- {
- hidden.report_mismatch(&concrete_type, tcx);
- }
- }
- }
-
- hidden.ty
-}
-
-fn find_opaque_ty_constraints_for_rpit(
- tcx: TyCtxt<'_>,
- def_id: LocalDefId,
- owner_def_id: LocalDefId,
-) -> Ty<'_> {
- use rustc_hir::{Expr, ImplItem, Item, TraitItem};
-
- struct ConstraintChecker<'tcx> {
- tcx: TyCtxt<'tcx>,
-
- /// def_id of the opaque type whose defining uses are being checked
- def_id: LocalDefId,
-
- found: ty::OpaqueHiddenType<'tcx>,
- }
-
- impl ConstraintChecker<'_> {
- #[instrument(skip(self), level = "debug")]
- fn check(&self, def_id: LocalDefId) {
- // Use borrowck to get the type with unerased regions.
- let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
- debug!(?concrete_opaque_types);
- for (&def_id, &concrete_type) in concrete_opaque_types {
- if def_id != self.def_id {
- // Ignore constraints for other opaque types.
- continue;
- }
-
- debug!(?concrete_type, "found constraint");
-
- if concrete_type.ty != self.found.ty
- && !(concrete_type, self.found).references_error()
- {
- self.found.report_mismatch(&concrete_type, self.tcx);
- }
- }
- }
- }
-
- impl<'tcx> intravisit::Visitor<'tcx> for ConstraintChecker<'tcx> {
- type NestedFilter = nested_filter::OnlyBodies;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
- fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
- if let hir::ExprKind::Closure(closure) = ex.kind {
- self.check(closure.def_id);
- }
- intravisit::walk_expr(self, ex);
- }
- fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_item(self, it);
- }
- }
- fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
- trace!(?it.owner_id);
- // The opaque type itself or its children are not within its reveal scope.
- if it.owner_id.def_id != self.def_id {
- self.check(it.owner_id.def_id);
- intravisit::walk_impl_item(self, it);
- }
- }
- fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
- trace!(?it.owner_id);
- self.check(it.owner_id.def_id);
- intravisit::walk_trait_item(self, it);
- }
- }
-
- let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
-
- if let Some(concrete) = concrete {
- let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
- debug!(?scope);
- let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
-
- match tcx.hir().get(scope) {
- Node::Item(it) => intravisit::walk_item(&mut locator, it),
- Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
- Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
- other => bug!("{:?} is not a valid scope for an opaque type item", other),
- }
- }
-
- concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
- let table = tcx.typeck(owner_def_id);
- if let Some(guar) = table.tainted_by_errors {
- // Some error in the
- // owner fn prevented us from populating
- // the `concrete_opaque_types` table.
- tcx.ty_error(guar)
- } else {
- table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
- // We failed to resolve the opaque type or it
- // resolves to itself. We interpret this as the
- // no values of the hidden type ever being constructed,
- // so we can just make the hidden type be `!`.
- // For backwards compatibility reasons, we fall back to
- // `()` until we the diverging default is changed.
- tcx.mk_diverging_default()
- })
- }
- })
-}
-
fn infer_placeholder_type<'a>(
tcx: TyCtxt<'a>,
def_id: LocalDefId,
@@ -893,14 +530,14 @@ fn infer_placeholder_type<'a>(
if let Some(ty) = ty.make_suggestable(tcx, false) {
err.span_suggestion(
span,
- &format!("provide a type for the {item}", item = kind),
+ format!("provide a type for the {item}", item = kind),
format!("{colon} {ty}"),
Applicability::MachineApplicable,
);
} else {
with_forced_trimmed_paths!(err.span_note(
tcx.hir().body(body_id).value.span,
- &format!("however, the inferred type `{ty}` cannot be named"),
+ format!("however, the inferred type `{ty}` cannot be named"),
));
}
}
@@ -921,7 +558,7 @@ fn infer_placeholder_type<'a>(
} else {
with_forced_trimmed_paths!(diag.span_note(
tcx.hir().body(body_id).value.span,
- &format!("however, the inferred type `{ty}` cannot be named"),
+ format!("however, the inferred type `{ty}` cannot be named"),
));
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
new file mode 100644
index 000000000..f7c5b4467
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -0,0 +1,298 @@
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
+
+use crate::errors::UnconstrainedOpaqueType;
+
+/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
+/// laid for "higher-order pattern unification".
+/// This ensures that inference is tractable.
+/// In particular, definitions of opaque types can only use other generics as arguments,
+/// and they cannot repeat an argument. Example:
+///
+/// ```ignore (illustrative)
+/// type Foo<A, B> = impl Bar<A, B>;
+///
+/// // Okay -- `Foo` is applied to two distinct, generic types.
+/// fn a<T, U>() -> Foo<T, U> { .. }
+///
+/// // Not okay -- `Foo` is applied to `T` twice.
+/// fn b<T>() -> Foo<T, T> { .. }
+///
+/// // Not okay -- `Foo` is applied to a non-generic type.
+/// fn b<T>() -> Foo<T, u32> { .. }
+/// ```
+#[instrument(skip(tcx), level = "debug")]
+pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let scope = tcx.hir().get_defining_scope(hir_id);
+ let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
+
+ debug!(?scope);
+
+ if scope == hir::CRATE_HIR_ID {
+ tcx.hir().walk_toplevel_module(&mut locator);
+ } else {
+ trace!("scope={:#?}", tcx.hir().get(scope));
+ match tcx.hir().get(scope) {
+ // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
+ // This allows our visitor to process the defining item itself, causing
+ // it to pick up any 'sibling' defining uses.
+ //
+ // For example, this code:
+ // ```
+ // fn foo() {
+ // type Blah = impl Debug;
+ // let my_closure = || -> Blah { true };
+ // }
+ // ```
+ //
+ // requires us to explicitly process `foo()` in order
+ // to notice the defining usage of `Blah`.
+ Node::Item(it) => locator.visit_item(it),
+ Node::ImplItem(it) => locator.visit_impl_item(it),
+ Node::TraitItem(it) => locator.visit_trait_item(it),
+ other => bug!("{:?} is not a valid scope for an opaque type item", other),
+ }
+ }
+
+ let Some(hidden) = locator.found else {
+ let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
+ span: tcx.def_span(def_id),
+ name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
+ what: match tcx.hir().get(scope) {
+ _ if scope == hir::CRATE_HIR_ID => "module",
+ Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
+ Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
+ _ => "item",
+ },
+ });
+ return tcx.ty_error(reported);
+ };
+
+ // Only check against typeck if we didn't already error
+ if !hidden.ty.references_error() {
+ for concrete_type in locator.typeck_types {
+ if concrete_type.ty != tcx.erase_regions(hidden.ty)
+ && !(concrete_type, hidden).references_error()
+ {
+ hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+ }
+ }
+ }
+
+ hidden.ty
+}
+
+struct TaitConstraintLocator<'tcx> {
+ tcx: TyCtxt<'tcx>,
+
+ /// def_id of the opaque type whose defining uses are being checked
+ def_id: LocalDefId,
+
+ /// as we walk the defining uses, we are checking that all of them
+ /// define the same hidden type. This variable is set to `Some`
+ /// with the first type that we find, and then later types are
+ /// checked against it (we also carry the span of that first
+ /// type).
+ found: Option<ty::OpaqueHiddenType<'tcx>>,
+
+ /// In the presence of dead code, typeck may figure out a hidden type
+ /// while borrowck will not. We collect these cases here and check at
+ /// the end that we actually found a type that matches (modulo regions).
+ typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
+}
+
+impl TaitConstraintLocator<'_> {
+ #[instrument(skip(self), level = "debug")]
+ fn check(&mut self, item_def_id: LocalDefId) {
+ // Don't try to check items that cannot possibly constrain the type.
+ if !self.tcx.has_typeck_results(item_def_id) {
+ debug!("no constraint: no typeck results");
+ return;
+ }
+ // Calling `mir_borrowck` can lead to cycle errors through
+ // const-checking, avoid calling it if we don't have to.
+ // ```rust
+ // type Foo = impl Fn() -> usize; // when computing type for this
+ // const fn bar() -> Foo {
+ // || 0usize
+ // }
+ // const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
+ // // because we again need to reveal `Foo` so we can check whether the
+ // // constant does not contain interior mutability.
+ // ```
+ let tables = self.tcx.typeck(item_def_id);
+ if let Some(guar) = tables.tainted_by_errors {
+ self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
+ return;
+ }
+ let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+ debug!("no constraints in typeck results");
+ return;
+ };
+ if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
+ self.typeck_types.push(typeck_hidden_ty);
+ }
+
+ // Use borrowck to get the type with unerased regions.
+ let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
+ debug!(?concrete_opaque_types);
+ if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
+ debug!(?concrete_type, "found constraint");
+ if let Some(prev) = &mut self.found {
+ if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
+ let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+ prev.ty = self.tcx.ty_error(guar);
+ }
+ } else {
+ self.found = Some(concrete_type);
+ }
+ }
+ }
+}
+
+impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
+ type NestedFilter = nested_filter::All;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.tcx.hir()
+ }
+ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+ if let hir::ExprKind::Closure(closure) = ex.kind {
+ self.check(closure.def_id);
+ }
+ intravisit::walk_expr(self, ex);
+ }
+ fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_item(self, it);
+ }
+ }
+ fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_impl_item(self, it);
+ }
+ }
+ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+ trace!(?it.owner_id);
+ self.check(it.owner_id.def_id);
+ intravisit::walk_trait_item(self, it);
+ }
+}
+
+pub(super) fn find_opaque_ty_constraints_for_rpit(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+ owner_def_id: LocalDefId,
+) -> Ty<'_> {
+ let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+
+ if let Some(concrete) = concrete {
+ let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
+ debug!(?scope);
+ let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
+
+ match tcx.hir().get(scope) {
+ Node::Item(it) => intravisit::walk_item(&mut locator, it),
+ Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
+ Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
+ other => bug!("{:?} is not a valid scope for an opaque type item", other),
+ }
+ }
+
+ concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
+ let table = tcx.typeck(owner_def_id);
+ if let Some(guar) = table.tainted_by_errors {
+ // Some error in the
+ // owner fn prevented us from populating
+ // the `concrete_opaque_types` table.
+ tcx.ty_error(guar)
+ } else {
+ table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+ // We failed to resolve the opaque type or it
+ // resolves to itself. We interpret this as the
+ // no values of the hidden type ever being constructed,
+ // so we can just make the hidden type be `!`.
+ // For backwards compatibility reasons, we fall back to
+ // `()` until we the diverging default is changed.
+ tcx.mk_diverging_default()
+ })
+ }
+ })
+}
+
+struct RpitConstraintChecker<'tcx> {
+ tcx: TyCtxt<'tcx>,
+
+ /// def_id of the opaque type whose defining uses are being checked
+ def_id: LocalDefId,
+
+ found: ty::OpaqueHiddenType<'tcx>,
+}
+
+impl RpitConstraintChecker<'_> {
+ #[instrument(skip(self), level = "debug")]
+ fn check(&self, def_id: LocalDefId) {
+ // Use borrowck to get the type with unerased regions.
+ let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
+ debug!(?concrete_opaque_types);
+ for (&def_id, &concrete_type) in concrete_opaque_types {
+ if def_id != self.def_id {
+ // Ignore constraints for other opaque types.
+ continue;
+ }
+
+ debug!(?concrete_type, "found constraint");
+
+ if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
+ {
+ self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
+ }
+ }
+ }
+}
+
+impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> {
+ type NestedFilter = nested_filter::OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.tcx.hir()
+ }
+ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+ if let hir::ExprKind::Closure(closure) = ex.kind {
+ self.check(closure.def_id);
+ }
+ intravisit::walk_expr(self, ex);
+ }
+ fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_item(self, it);
+ }
+ }
+ fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+ trace!(?it.owner_id);
+ // The opaque type itself or its children are not within its reveal scope.
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
+ intravisit::walk_impl_item(self, it);
+ }
+ }
+ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+ trace!(?it.owner_id);
+ self.check(it.owner_id.def_id);
+ intravisit::walk_trait_item(self, it);
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index e18b0f082..9200c2aec 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -59,7 +59,7 @@ struct ParameterCollector {
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
- ty::Alias(ty::Projection, ..) if !self.include_nonconstraining => {
+ ty::Alias(ty::Projection | ty::Inherent, ..) if !self.include_nonconstraining => {
// projections are not injective
return ControlFlow::Continue(());
}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 2a3a68348..6e7eb4f6c 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
MultiSpan,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty};
use rustc_span::{symbol::Ident, Span, Symbol};
#[derive(Diagnostic)]
@@ -108,6 +108,14 @@ pub struct CopyImplOnNonAdt {
}
#[derive(Diagnostic)]
+#[diag(hir_analysis_const_param_ty_impl_on_non_adt)]
+pub struct ConstParamTyImplOnNonAdt {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
pub struct TraitObjectDeclaredWithNoTraits {
#[primary_span]
@@ -504,11 +512,23 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
pub(crate) struct ReturnTypeNotationMissingMethod {
#[primary_span]
pub span: Span,
- pub trait_name: Symbol,
+ pub ty_name: String,
pub assoc_name: Symbol,
}
#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_conflicting_bound)]
+#[note]
+pub(crate) struct ReturnTypeNotationConflictingBound<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ pub ty_name: String,
+ pub assoc_name: Symbol,
+ pub first_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+ pub second_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+}
+
+#[derive(Diagnostic)]
#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
pub(crate) struct PlaceholderNotAllowedItemSignatures {
#[primary_span]
@@ -631,3 +651,209 @@ pub(crate) struct SIMDFFIHighlyExperimental {
pub span: Span,
pub snip: String,
}
+
+#[derive(Diagnostic)]
+
+pub enum ImplNotMarkedDefault {
+ #[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
+ #[note]
+ Ok {
+ #[primary_span]
+ #[label]
+ span: Span,
+ #[label(hir_analysis_ok_label)]
+ ok_label: Span,
+ ident: Symbol,
+ },
+ #[diag(hir_analysis_impl_not_marked_default_err, code = "E0520")]
+ #[note]
+ Err {
+ #[primary_span]
+ span: Span,
+ cname: Symbol,
+ ident: Symbol,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_missing_trait_item, code = "E0046")]
+pub(crate) struct MissingTraitItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub missing_trait_item_label: Vec<MissingTraitItemLabel>,
+ #[subdiagnostic]
+ pub missing_trait_item: Vec<MissingTraitItemSuggestion>,
+ #[subdiagnostic]
+ pub missing_trait_item_none: Vec<MissingTraitItemSuggestionNone>,
+ pub missing_items_msg: String,
+}
+
+#[derive(Subdiagnostic)]
+#[label(hir_analysis_missing_trait_item_label)]
+pub(crate) struct MissingTraitItemLabel {
+ #[primary_span]
+ pub span: Span,
+ pub item: Symbol,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ hir_analysis_missing_trait_item_suggestion,
+ style = "tool-only",
+ applicability = "has-placeholders",
+ code = "{code}"
+)]
+pub(crate) struct MissingTraitItemSuggestion {
+ #[primary_span]
+ pub span: Span,
+ pub code: String,
+ pub snippet: String,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ hir_analysis_missing_trait_item_suggestion,
+ style = "hidden",
+ applicability = "has-placeholders",
+ code = "{code}"
+)]
+pub(crate) struct MissingTraitItemSuggestionNone {
+ #[primary_span]
+ pub span: Span,
+ pub code: String,
+ pub snippet: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_missing_one_of_trait_item, code = "E0046")]
+pub(crate) struct MissingOneOfTraitItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[note]
+ pub note: Option<Span>,
+ pub missing_items_msg: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_missing_trait_item_unstable, code = "E0046")]
+#[note]
+pub(crate) struct MissingTraitItemUnstable {
+ #[primary_span]
+ pub span: Span,
+ #[note(hir_analysis_some_note)]
+ pub some_note: bool,
+ #[note(hir_analysis_none_note)]
+ pub none_note: bool,
+ pub missing_item_name: Symbol,
+ pub feature: Symbol,
+ pub reason: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_transparent_enum_variant, code = "E0731")]
+pub(crate) struct TransparentEnumVariant {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(hir_analysis_multi_label)]
+ pub spans: Vec<Span>,
+ #[label(hir_analysis_many_label)]
+ pub many: Option<Span>,
+ pub number: usize,
+ pub path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_transparent_non_zero_sized_enum, code = "E0690")]
+pub(crate) struct TransparentNonZeroSizedEnum<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(hir_analysis_labels)]
+ pub spans: Vec<Span>,
+ pub field_count: usize,
+ pub desc: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_transparent_non_zero_sized, code = "E0690")]
+pub(crate) struct TransparentNonZeroSized<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(hir_analysis_labels)]
+ pub spans: Vec<Span>,
+ pub field_count: usize,
+ pub desc: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_too_large_static)]
+pub(crate) struct TooLargeStatic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_specialization_trait)]
+#[help]
+pub(crate) struct SpecializationTrait {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_closure_implicit_hrtb)]
+pub(crate) struct ClosureImplicitHrtb {
+ #[primary_span]
+ pub spans: Vec<Span>,
+ #[label]
+ pub for_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_empty_specialization)]
+pub(crate) struct EmptySpecialization {
+ #[primary_span]
+ pub span: Span,
+ #[note]
+ pub base_impl_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_const_specialize)]
+pub(crate) struct ConstSpecialize {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_static_specialize)]
+pub(crate) struct StaticSpecialize {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_missing_tilde_const)]
+pub(crate) struct MissingTildeConst {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum DropImplPolarity {
+ #[diag(hir_analysis_drop_impl_negative)]
+ Negative {
+ #[primary_span]
+ span: Span,
+ },
+ #[diag(hir_analysis_drop_impl_reservation)]
+ Reservation {
+ #[primary_span]
+ span: Span,
+ },
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 8269a6dde..e4c6e6e39 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{ForeignItem, ForeignItemKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt};
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 82a96f8e6..612d4ff3d 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::{Span, Symbol};
@@ -76,7 +76,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
// (#36836)
tcx.sess.delay_span_bug(
tcx.def_span(impl_def_id),
- &format!(
+ format!(
"potentially unconstrained type parameters weren't evaluated: {:?}",
impl_self_ty,
),
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index eb2fc3952..e84da2519 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -65,8 +65,8 @@
//! cause use after frees with purely safe code in the same way as specializing
//! on traits with methods can.
-use crate::constrained_generic_params as cgp;
use crate::errors::SubstsOnOverriddenImpl;
+use crate::{constrained_generic_params as cgp, errors};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
@@ -80,7 +80,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
+use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
@@ -100,12 +100,19 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti
// Implementing a normal trait isn't a specialization.
return None;
}
+ if trait_def.is_marker {
+ // Overlapping marker implementations are not really specializations.
+ return None;
+ }
Some(impl2_node)
}
/// Check that `impl1` is a sound specialization
#[instrument(level = "debug", skip(tcx))]
fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+ let span = tcx.def_span(impl1_def_id);
+ check_has_items(tcx, impl1_def_id, impl2_node, span);
+
if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
let impl2_def_id = impl2_node.def_id();
debug!(?impl2_def_id, ?impl2_substs);
@@ -116,7 +123,6 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
};
- let span = tcx.def_span(impl1_def_id);
check_constness(tcx, impl1_def_id, impl2_node, span);
check_static_lifetimes(tcx, &parent_substs, span);
check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
@@ -124,6 +130,13 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
}
}
+fn check_has_items(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) {
+ if let Node::Impl(impl2_id) = impl2_node && tcx.associated_item_def_ids(impl1_def_id).is_empty() {
+ let base_impl_span = tcx.def_span(impl2_id);
+ tcx.sess.emit_err(errors::EmptySpecialization { span, base_impl_span });
+ }
+}
+
/// Check that the specializing impl `impl1` is at least as const as the base
/// impl `impl2`
fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, span: Span) {
@@ -137,9 +150,7 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
if let hir::Constness::Const = impl2_constness {
if let hir::Constness::NotConst = impl1_constness {
- tcx.sess
- .struct_span_err(span, "cannot specialize on const impl with non-const impl")
- .emit();
+ tcx.sess.emit_err(errors::ConstSpecialize { span });
}
}
}
@@ -169,8 +180,21 @@ fn get_impl_substs(
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
- let impl2_substs =
- translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+ let impl1_span = tcx.def_span(impl1_def_id);
+ let impl2_substs = translate_substs_with_cause(
+ infcx,
+ param_env,
+ impl1_def_id.to_def_id(),
+ impl1_substs,
+ impl2_node,
+ |_, span| {
+ traits::ObligationCause::new(
+ impl1_span,
+ impl1_def_id,
+ traits::ObligationCauseCode::BindingObligation(impl2_node.def_id(), span),
+ )
+ },
+ );
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
@@ -274,7 +298,7 @@ fn check_duplicate_params<'tcx>(
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
let param = impl1_substs[duplicate.0 as usize];
tcx.sess
- .struct_span_err(span, &format!("specializing impl repeats parameter `{}`", param))
+ .struct_span_err(span, format!("specializing impl repeats parameter `{}`", param))
.emit();
}
}
@@ -293,7 +317,7 @@ fn check_static_lifetimes<'tcx>(
span: Span,
) {
if tcx.any_free_region_meets(parent_substs, |r| r.is_static()) {
- tcx.sess.struct_span_err(span, "cannot specialize on `'static` lifetime").emit();
+ tcx.sess.emit_err(errors::StaticSpecialize { span });
}
}
@@ -368,7 +392,7 @@ fn check_predicates<'tcx>(
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
.unwrap();
- assert!(!obligations.needs_infer());
+ assert!(!obligations.has_infer());
impl2_predicates
.extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
}
@@ -438,7 +462,7 @@ fn trait_predicates_eq<'tcx>(
// the one on the base.
match (trait_pred2.constness, trait_pred1.constness) {
(ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => {
- tcx.sess.struct_span_err(span, "missing `~const` qualifier for specialization").emit();
+ tcx.sess.emit_err(errors::MissingTildeConst { span });
}
_ => {}
}
@@ -466,7 +490,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
tcx.sess
.struct_span_err(
span,
- &format!(
+ format!(
"cannot specialize on trait `{}`",
tcx.def_path_str(trait_ref.def_id),
),
@@ -481,7 +505,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
tcx.sess
.struct_span_err(
span,
- &format!("cannot specialize on associated type `{projection_ty} == {term}`",),
+ format!("cannot specialize on associated type `{projection_ty} == {term}`",),
)
.emit();
}
@@ -497,7 +521,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
}
_ => {
tcx.sess
- .struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
+ .struct_span_err(span, format!("cannot specialize on predicate `{}`", predicate))
.emit();
}
}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 27e561803..5cd2cd50c 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -99,12 +99,12 @@ mod variance;
use rustc_errors::ErrorGuaranteed;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir as hir;
use rustc_hir::Node;
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_macros::fluent_messages;
use rustc_middle::middle;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util;
use rustc_session::{config::EntryFnType, parse::feature_err};
@@ -116,7 +116,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
use std::ops::Not;
-use astconv::AstConv;
+use astconv::{AstConv, OnlySelfBounds};
use bounds::Bounds;
fluent_messages! { "../messages.ftl" }
@@ -496,8 +496,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
});
- tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
-
check_unused::check_crate(tcx);
check_for_entry_fn(tcx);
@@ -530,9 +528,11 @@ pub fn hir_trait_to_predicates<'tcx>(
hir_trait,
DUMMY_SP,
ty::BoundConstness::NotConst,
+ ty::ImplPolarity::Positive,
self_ty,
&mut bounds,
true,
+ OnlySelfBounds(false),
);
bounds
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index d53c429ca..0cd2fc1aa 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -210,6 +210,9 @@ fn insert_required_predicates_to_be_wf<'tcx>(
);
}
+ // FIXME(inherent_associated_types): Handle this case properly.
+ ty::Alias(ty::Inherent, _) => {}
+
_ => {}
}
}
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index da72d2584..a8596c707 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -1,7 +1,7 @@
use hir::Node;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
use rustc_span::symbol::sym;
@@ -61,7 +61,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
let span = tcx.def_span(item_def_id);
let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
- for p in &pred {
+ for p in pred {
err.note(p);
}
err.emit();
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
index 0bfbf99cb..c37dff61b 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -48,7 +48,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
&self,
mut err: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- err.note(&format!(
+ err.note(format!(
"certain types, like `{}`, must be casted before passing them to a \
variadic function, because of arcane ABI rules dictated by the C \
standard",
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 8f4d81ec3..ee3457282 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -395,7 +395,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
) -> String {
let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(hir::Node::fn_sig);
let is_used_in_input = |def_id| {
- fn_sig.map_or(false, |fn_sig| {
+ fn_sig.is_some_and(|fn_sig| {
fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(
None,
@@ -480,7 +480,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let span = self.path_segment.ident.span;
let msg = self.create_error_message();
- self.tcx.sess.struct_span_err_with_code(span, &msg, self.code())
+ self.tcx.sess.struct_span_err_with_code(span, msg, self.code())
}
/// Builds the `expected 1 type argument / supplied 2 type arguments` message.
@@ -602,7 +602,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
err.span_suggestion_verbose(
span.shrink_to_hi(),
- &msg,
+ msg,
sugg,
Applicability::HasPlaceholders,
);
@@ -625,7 +625,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
debug!("sugg: {:?}", sugg);
- err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders);
+ err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
}
AngleBrackets::Implied => {
// We never encounter missing lifetimes in situations in which lifetimes are elided
@@ -652,7 +652,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
err.span_suggestion_verbose(
span.shrink_to_hi(),
- &msg,
+ msg,
sugg,
Applicability::HasPlaceholders,
);
@@ -683,7 +683,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
debug!("sugg: {:?}", sugg);
- err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders);
+ err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
}
}
}
@@ -885,7 +885,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
err.span_suggestion(
span_redundant_lt_args,
- &msg_lifetimes,
+ msg_lifetimes,
"",
Applicability::MaybeIncorrect,
);
@@ -927,7 +927,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
err.span_suggestion(
span_redundant_type_or_const_args,
- &msg_types_or_consts,
+ msg_types_or_consts,
"",
Applicability::MaybeIncorrect,
);
@@ -943,7 +943,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
if !suggestions.is_empty() {
err.multipart_suggestion_verbose(
- &format!(
+ format!(
"replace the generic bound{s} with the associated type{s}",
s = pluralize!(unbound_types.len())
),
@@ -969,7 +969,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
},
);
- err.span_suggestion(span, &msg, "", Applicability::MaybeIncorrect);
+ err.span_suggestion(span, msg, "", Applicability::MaybeIncorrect);
} else if redundant_lifetime_args && redundant_type_or_const_args {
remove_lifetime_args(err);
remove_type_or_const_args(err);
@@ -1029,7 +1029,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
)
};
- err.span_note(spans, &msg);
+ err.span_note(spans, msg);
}
/// Add note if `impl Trait` is explicitly specified.
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 408bec71e..6f0afae1b 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -92,7 +92,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn build_constraints_for_item(&mut self, def_id: LocalDefId) {
let tcx = self.tcx();
- debug!("build_constraints_for_item({})", tcx.def_path_str(def_id.to_def_id()));
+ debug!("build_constraints_for_item({})", tcx.def_path_str(def_id));
// Skip items with no generics - there's nothing to infer in them.
if tcx.generics_of(def_id).count() == 0 {
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 0a45119ff..3ebd9e134 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -6,7 +6,7 @@
use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
use std::ops::ControlFlow;
@@ -105,7 +105,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
self.variances[ebr.index as usize] = ty::Invariant;
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
#[instrument(level = "trace", skip(self), ret)]
@@ -153,8 +153,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
let mut collector =
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id);
- for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() {
- let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
+ for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) {
debug!(?pred);
// We only ignore opaque type substs if the opaque type is the outermost type.