summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_hir_analysis
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis')
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl (renamed from compiler/rustc_hir_analysis/locales/en-US.ftl)74
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs123
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs430
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs81
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs204
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs125
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs72
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs256
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs76
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs200
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs78
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs141
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs234
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs44
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs51
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs65
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/test.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/variance/test.rs9
37 files changed, 1544 insertions, 926 deletions
diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 1d313945b..1d7965ff5 100644
--- a/compiler/rustc_hir_analysis/locales/en-US.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -42,6 +42,9 @@ hir_analysis_assoc_type_binding_not_allowed =
associated type bindings are not allowed here
.label = associated type not allowed here
+hir_analysis_parenthesized_fn_trait_expansion =
+ parenthesized trait syntax expands to `{$expanded_type}`
+
hir_analysis_typeof_reserved_keyword_used =
`typeof` is a reserved keyword but unimplemented
.suggestion = consider replacing `typeof(...)` with an actual type
@@ -89,14 +92,14 @@ hir_analysis_missing_type_params =
.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` may not be implemented for this type; the type has a destructor
+ 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` may not be implemented for this type
+ 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 =
@@ -125,9 +128,14 @@ hir_analysis_where_clause_on_main = `main` function is not allowed to have a `wh
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
.suggestion = remove this annotation
+hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
+
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_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
+ .label = `start` is not allowed to have `#[target_feature]`
+
hir_analysis_start_not_async = `start` is not allowed to be `async`
.label = `start` is not allowed to be `async`
@@ -155,3 +163,65 @@ hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
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_variances_of = {$variances_of}
+
+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_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
+
+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_invalid_union_field_sugg =
+ wrap the field type in `ManuallyDrop<...>`
+
+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_return_type_notation_equality_bound =
+ return type notation is not allowed to use type equality
+
+hir_analysis_return_type_notation_missing_method =
+ cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
+
+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_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_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
+
+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_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_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
+
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+ .note = required by this annotation
+
+hir_analysis_must_implement_not_function = not a function
+
+hir_analysis_must_implement_not_function_span_note = required by this annotation
+
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
+
+hir_analysis_function_not_found_in_trait = function not found in this trait
+
+hir_analysis_functions_names_duplicated = functions names are duplicated
+ .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+
+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
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index c49e4d9d5..113c3f08a 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -1,10 +1,14 @@
use crate::astconv::AstConv;
-use crate::errors::{ManualImplementation, MissingTypeParams};
+use crate::errors::{
+ AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
+ ParenthesizedFnTraitExpansion,
+};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::FulfillmentError;
+use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, Ty};
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
@@ -51,7 +55,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let trait_def = self.tcx().trait_def(trait_def_id);
if !trait_def.paren_sugar {
- if trait_segment.args().parenthesized {
+ if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar {
// For now, require that parenthetical notation be used only with `Fn()` etc.
let mut err = feature_err(
&self.tcx().sess.parse_sess,
@@ -67,7 +71,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let sess = self.tcx().sess;
- if !trait_segment.args().parenthesized {
+ if trait_segment.args().parenthesized != hir::GenericArgsParentheses::ParenSugar {
// For now, require that parenthetical notation be used only with `Fn()` etc.
let mut err = feature_err(
&sess.parse_sess,
@@ -78,43 +82,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Do not suggest the other syntax if we are in trait impl:
// the desugaring would contain an associated type constraint.
if !is_impl {
- let args = trait_segment
- .args
- .as_ref()
- .and_then(|args| args.args.get(0))
- .and_then(|arg| match arg {
- hir::GenericArg::Type(ty) => match ty.kind {
- hir::TyKind::Tup(t) => t
- .iter()
- .map(|e| sess.source_map().span_to_snippet(e.span))
- .collect::<Result<Vec<_>, _>>()
- .map(|a| a.join(", ")),
- _ => sess.source_map().span_to_snippet(ty.span),
- }
- .map(|s| format!("({})", s))
- .ok(),
- _ => None,
- })
- .unwrap_or_else(|| "()".to_string());
- let ret = trait_segment
- .args()
- .bindings
- .iter()
- .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
- (true, hir::TypeBindingKind::Equality { term }) => {
- let span = match term {
- hir::Term::Ty(ty) => ty.span,
- hir::Term::Const(c) => self.tcx().hir().span(c.hir_id),
- };
- sess.source_map().span_to_snippet(span).ok()
- }
- _ => None,
- })
- .unwrap_or_else(|| "()".to_string());
err.span_suggestion(
span,
"use parenthetical notation instead",
- format!("{}{} -> {}", trait_segment.ident, args, ret),
+ fn_trait_to_string(self.tcx(), trait_segment, true),
Applicability::MaybeIncorrect,
);
}
@@ -512,8 +483,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
[segment] if segment.args.is_none() => {
trait_bound_spans = vec![segment.ident.span];
associated_types = associated_types
- .into_iter()
- .map(|(_, items)| (segment.ident.span, items))
+ .into_values()
+ .map(|items| (segment.ident.span, items))
.collect();
}
_ => {}
@@ -629,3 +600,77 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.emit();
}
}
+
+/// Emits an error regarding forbidden type binding associations
+pub fn prohibit_assoc_ty_binding(
+ tcx: TyCtxt<'_>,
+ span: Span,
+ segment: Option<(&hir::PathSegment<'_>, Span)>,
+) {
+ tcx.sess.emit_err(AssocTypeBindingNotAllowed {
+ span,
+ fn_trait_expansion: if let Some((segment, span)) = segment
+ && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
+ {
+ Some(ParenthesizedFnTraitExpansion {
+ span,
+ expanded_type: fn_trait_to_string(tcx, segment, false),
+ })
+ } else {
+ None
+ },
+ });
+}
+
+pub(crate) fn fn_trait_to_string(
+ tcx: TyCtxt<'_>,
+ trait_segment: &hir::PathSegment<'_>,
+ parenthesized: bool,
+) -> String {
+ let args = trait_segment
+ .args
+ .as_ref()
+ .and_then(|args| args.args.get(0))
+ .and_then(|arg| match arg {
+ hir::GenericArg::Type(ty) => match ty.kind {
+ hir::TyKind::Tup(t) => t
+ .iter()
+ .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
+ .collect::<Result<Vec<_>, _>>()
+ .map(|a| a.join(", ")),
+ _ => tcx.sess.source_map().span_to_snippet(ty.span),
+ }
+ .map(|s| {
+ // `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
+ if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) }
+ })
+ .ok(),
+ _ => None,
+ })
+ .unwrap_or_else(|| "()".to_string());
+
+ let ret = trait_segment
+ .args()
+ .bindings
+ .iter()
+ .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
+ (true, hir::TypeBindingKind::Equality { term }) => {
+ let span = match term {
+ hir::Term::Ty(ty) => ty.span,
+ hir::Term::Const(c) => tcx.hir().span(c.hir_id),
+ };
+
+ (span != tcx.hir().span(trait_segment.hir_id))
+ .then_some(tcx.sess.source_map().span_to_snippet(span).ok())
+ .flatten()
+ }
+ _ => None,
+ })
+ .unwrap_or_else(|| "()".to_string());
+
+ if parenthesized {
+ format!("{}{} -> {}", trait_segment.ident, args, ret)
+ } else {
+ format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 7f6518ffd..3b5c67de2 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -1,9 +1,8 @@
use super::IsMethodCall;
use crate::astconv::{
- CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
- GenericArgCountResult, GenericArgPosition,
+ errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
+ GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
};
-use crate::errors::AssocTypeBindingNotAllowed;
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
use rustc_ast::ast::ParamKindOrd;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
@@ -433,7 +432,7 @@ pub(crate) fn check_generic_arg_count(
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
- prohibit_assoc_ty_binding(tcx, b.span);
+ prohibit_assoc_ty_binding(tcx, b.span, None);
}
let explicit_late_bound =
@@ -589,11 +588,6 @@ pub(crate) fn check_generic_arg_count(
}
}
-/// Emits an error regarding forbidden type binding associations
-pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
- tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
-}
-
/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
/// are present. This is used both for datatypes and function calls.
pub(crate) fn prohibit_explicit_late_bound_lifetimes(
@@ -618,7 +612,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
if position == GenericArgPosition::Value
&& args.num_lifetime_params() != param_counts.lifetimes
{
- let mut err = tcx.sess.struct_span_err(span, msg);
+ let mut err = struct_span_err!(tcx.sess, span, E0794, "{}", msg);
err.span_note(span_late, note);
err.emit();
} else {
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index f5ce02c9e..8d1156c17 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -5,9 +5,8 @@
mod errors;
pub mod generics;
-use crate::astconv::generics::{
- check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
-};
+use crate::astconv::errors::prohibit_assoc_ty_binding;
+use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
use crate::bounds::Bounds;
use crate::collect::HirPlaceholderCollector;
use crate::errors::{
@@ -32,10 +31,11 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::middle::stability::AllowUnstable;
+use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::DynKind;
use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+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;
@@ -76,7 +76,7 @@ pub trait AstConv<'tcx> {
fn get_type_parameter_bounds(
&self,
span: Span,
- def_id: DefId,
+ def_id: LocalDefId,
assoc_name: Ident,
) -> ty::GenericPredicates<'tcx>;
@@ -295,7 +295,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::BoundConstness::NotConst,
);
if let Some(b) = item_segment.args().bindings.first() {
- prohibit_assoc_ty_binding(self.tcx(), b.span);
+ prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
}
substs
@@ -631,7 +631,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
);
if let Some(b) = item_segment.args().bindings.first() {
- prohibit_assoc_ty_binding(self.tcx(), b.span);
+ prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
}
args
@@ -825,7 +825,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
constness,
);
if let Some(b) = trait_segment.args().bindings.first() {
- prohibit_assoc_ty_binding(self.tcx(), b.span);
+ prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
}
self.tcx().mk_trait_ref(trait_def_id, substs)
}
@@ -854,16 +854,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
}
- fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
- self.tcx()
- .associated_items(trait_def_id)
- .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
- .is_some()
- }
- fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+ fn trait_defines_associated_item_named(
+ &self,
+ trait_def_id: DefId,
+ assoc_kind: ty::AssocKind,
+ assoc_name: Ident,
+ ) -> bool {
self.tcx()
.associated_items(trait_def_id)
- .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id)
+ .find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id)
.is_some()
}
@@ -1087,24 +1086,44 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let tcx = self.tcx();
- let candidate =
- if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
- // Simple case: X is defined in the current trait.
+ let return_type_notation =
+ binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation;
+
+ let candidate = if return_type_notation {
+ if self.trait_defines_associated_item_named(
+ trait_ref.def_id(),
+ ty::AssocKind::Fn,
+ binding.item_name,
+ ) {
trait_ref
} else {
- // Otherwise, we have to walk through the supertraits to find
- // those that do.
- self.one_bound_for_assoc_type(
- || traits::supertraits(tcx, trait_ref),
- trait_ref.print_only_trait_path(),
- binding.item_name,
- path_span,
- match binding.kind {
- ConvertedBindingKind::Equality(term) => Some(term),
- _ => None,
- },
- )?
- };
+ 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,
+ }));
+ }
+ } else if self.trait_defines_associated_item_named(
+ trait_ref.def_id(),
+ ty::AssocKind::Type,
+ binding.item_name,
+ ) {
+ // Simple case: X is defined in the current trait.
+ trait_ref
+ } else {
+ // Otherwise, we have to walk through the supertraits to find
+ // those that do.
+ self.one_bound_for_assoc_type(
+ || traits::supertraits(tcx, trait_ref),
+ trait_ref.print_only_trait_path(),
+ binding.item_name,
+ path_span,
+ match binding.kind {
+ ConvertedBindingKind::Equality(term) => Some(term),
+ _ => None,
+ },
+ )?
+ };
let (assoc_ident, def_scope) =
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
@@ -1116,9 +1135,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.filter_by_name_unhygienic(assoc_ident.name)
.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
};
- let assoc_item = find_item_of_kind(ty::AssocKind::Type)
- .or_else(|| find_item_of_kind(ty::AssocKind::Const))
- .expect("missing associated type");
+ let assoc_item = if return_type_notation {
+ find_item_of_kind(ty::AssocKind::Fn)
+ } else {
+ find_item_of_kind(ty::AssocKind::Type)
+ .or_else(|| find_item_of_kind(ty::AssocKind::Const))
+ }
+ .expect("missing associated type");
if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
tcx.sess
@@ -1135,7 +1158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
dup_bindings
.entry(assoc_item.def_id)
.and_modify(|prev_span| {
- self.tcx().sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
+ tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
span: binding.span,
prev_span: *prev_span,
item_name: binding.item_name,
@@ -1145,28 +1168,100 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.or_insert(binding.span);
}
- // Include substitutions for generic parameters of associated types
- let projection_ty = candidate.map_bound(|trait_ref| {
- let ident = Ident::new(assoc_item.name, binding.item_name.span);
- let item_segment = hir::PathSegment {
- ident,
- hir_id: binding.hir_id,
- res: Res::Err,
- args: Some(binding.gen_args),
- infer_args: false,
+ let projection_ty = if return_type_notation {
+ // If we have an method return type bound, then we need to substitute
+ // the method's early bound params with suitable late-bound params.
+ let mut num_bound_vars = candidate.bound_vars().len();
+ let substs =
+ candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| {
+ let subst = match param.kind {
+ GenericParamDefKind::Lifetime => tcx
+ .mk_re_late_bound(
+ ty::INNERMOST,
+ ty::BoundRegion {
+ var: ty::BoundVar::from_usize(num_bound_vars),
+ kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+ },
+ )
+ .into(),
+ GenericParamDefKind::Type { .. } => tcx
+ .mk_bound(
+ ty::INNERMOST,
+ ty::BoundTy {
+ var: ty::BoundVar::from_usize(num_bound_vars),
+ kind: ty::BoundTyKind::Param(param.def_id, param.name),
+ },
+ )
+ .into(),
+ GenericParamDefKind::Const { .. } => {
+ let ty = tcx
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("ct params cannot have early bound vars");
+ tcx.mk_const(
+ ty::ConstKind::Bound(
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(num_bound_vars),
+ ),
+ ty,
+ )
+ .into()
+ }
+ };
+ num_bound_vars += 1;
+ subst
+ });
+
+ // Next, we need to check that the return-type notation is being used on
+ // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
+ let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output();
+ let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
+ && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
+ {
+ alias_ty
+ } else {
+ return Err(self.tcx().sess.emit_err(
+ crate::errors::ReturnTypeNotationOnNonRpitit {
+ span: binding.span,
+ ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
+ fn_span: tcx.hir().span_if_local(assoc_item.def_id),
+ note: (),
+ },
+ ));
};
- let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
- path_span,
- assoc_item.def_id,
- &item_segment,
- trait_ref.substs,
- );
+ // Finally, move the fn return type's bound vars over to account for the early bound
+ // params (and trait ref's late bound params). This logic is very similar to
+ // `Predicate::subst_supertrait`, and it's no coincidence why.
+ let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
+ let subst_output = ty::EarlyBinder(shifted_output).subst(tcx, substs);
+
+ let bound_vars = tcx.late_bound_vars(binding.hir_id);
+ ty::Binder::bind_with_vars(subst_output, bound_vars)
+ } else {
+ // Include substitutions for generic parameters of associated types
+ candidate.map_bound(|trait_ref| {
+ let ident = Ident::new(assoc_item.name, binding.item_name.span);
+ let item_segment = hir::PathSegment {
+ ident,
+ hir_id: binding.hir_id,
+ res: Res::Err,
+ args: Some(binding.gen_args),
+ infer_args: false,
+ };
+
+ let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
+ path_span,
+ assoc_item.def_id,
+ &item_segment,
+ trait_ref.substs,
+ );
- debug!(?substs_trait_ref_and_assoc_item);
+ debug!(?substs_trait_ref_and_assoc_item);
- self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
- });
+ tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
+ })
+ };
if !speculative {
// Find any late-bound regions declared in `ty` that are not
@@ -1206,6 +1301,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
match binding.kind {
+ ConvertedBindingKind::Equality(..) if return_type_notation => {
+ return Err(self.tcx().sess.emit_err(
+ crate::errors::ReturnTypeNotationEqualityBound { span: binding.span },
+ ));
+ }
ConvertedBindingKind::Equality(mut term) => {
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
// the "projection predicate" for:
@@ -1267,7 +1367,7 @@ 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, candidate.bound_vars());
+ self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
}
}
Ok(())
@@ -1336,7 +1436,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(),
},
ty::PredicateKind::WellFormed(_)
- | ty::PredicateKind::AliasEq(..)
+ | ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::Subtype(_)
@@ -1426,14 +1526,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for (base_trait_ref, span, constness) in regular_traits_refs_spans {
assert_eq!(constness, ty::BoundConstness::NotConst);
+ let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
+ for pred in traits::elaborate(tcx, [base_pred]) {
+ debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
- for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
- debug!(
- "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`",
- obligation.predicate
- );
-
- let bound_predicate = obligation.predicate.kind();
+ let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
let pred = bound_predicate.rebind(pred);
@@ -1441,6 +1538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.associated_items(pred.def_id())
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
+ .filter(|item| tcx.opt_rpitit_info(item.def_id).is_none())
.map(|item| item.def_id),
);
}
@@ -1565,39 +1663,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
})
});
- let existential_projections = projection_bounds.iter().map(|(bound, _)| {
- bound.map_bound(|mut b| {
- assert_eq!(b.projection_ty.self_ty(), dummy_self);
-
- // Like for trait refs, verify that `dummy_self` did not leak inside default type
- // parameters.
- let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
- if arg.walk().any(|arg| arg == dummy_self.into()) {
- return true;
+ let existential_projections = projection_bounds
+ .iter()
+ // We filter out traits that don't have `Self` as their self type above,
+ // we need to do the same for projections.
+ .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
+ .map(|(bound, _)| {
+ bound.map_bound(|mut b| {
+ assert_eq!(b.projection_ty.self_ty(), dummy_self);
+
+ // Like for trait refs, verify that `dummy_self` did not leak inside default type
+ // parameters.
+ let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
+ if arg.walk().any(|arg| arg == dummy_self.into()) {
+ return true;
+ }
+ false
+ });
+ if references_self {
+ let guar = tcx.sess.delay_span_bug(
+ span,
+ "trait object projection bounds reference `Self`",
+ );
+ let substs: Vec<_> = b
+ .projection_ty
+ .substs
+ .iter()
+ .map(|arg| {
+ if arg.walk().any(|arg| arg == dummy_self.into()) {
+ return tcx.ty_error(guar).into();
+ }
+ arg
+ })
+ .collect();
+ b.projection_ty.substs = tcx.mk_substs(&substs);
}
- false
- });
- if references_self {
- let guar = tcx
- .sess
- .delay_span_bug(span, "trait object projection bounds reference `Self`");
- let substs: Vec<_> = b
- .projection_ty
- .substs
- .iter()
- .map(|arg| {
- if arg.walk().any(|arg| arg == dummy_self.into()) {
- return tcx.ty_error(guar).into();
- }
- arg
- })
- .collect();
- b.projection_ty.substs = tcx.mk_substs(&substs);
- }
- ty::ExistentialProjection::erase_self_ty(tcx, b)
- })
- });
+ ty::ExistentialProjection::erase_self_ty(tcx, b)
+ })
+ });
let regular_trait_predicates = existential_trait_refs
.map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
@@ -1773,9 +1877,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty_param_def_id, assoc_name, span,
);
- let predicates = &self
- .get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
- .predicates;
+ let predicates =
+ &self.get_type_parameter_bounds(span, ty_param_def_id, assoc_name).predicates;
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
@@ -1811,10 +1914,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
{
- let mut matching_candidates = all_candidates()
- .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
- let mut const_candidates = all_candidates()
- .filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name));
+ let mut matching_candidates = all_candidates().filter(|r| {
+ self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name)
+ });
+ let mut const_candidates = all_candidates().filter(|r| {
+ self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
+ });
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
(Some(bound), _) => (bound, matching_candidates.next()),
@@ -2226,47 +2331,66 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let param_env = tcx.param_env(block.owner.to_def_id());
let cause = ObligationCause::misc(span, block.owner.def_id);
+
let mut fulfillment_errors = Vec::new();
- let mut applicable_candidates: Vec<_> = candidates
- .iter()
- .filter_map(|&(impl_, (assoc_item, def_scope))| {
- infcx.probe(|_| {
- let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+ let mut applicable_candidates: Vec<_> = infcx.probe(|_| {
+ let universe = infcx.create_next_universe();
+
+ // Regions are not considered during selection.
+ let self_ty = tcx.replace_escaping_bound_vars_uncached(
+ self_ty,
+ FnMutDelegate {
+ regions: &mut |_| tcx.lifetimes.re_erased,
+ types: &mut |bv| {
+ tcx.mk_placeholder(ty::PlaceholderType { universe, bound: bv })
+ },
+ consts: &mut |bv, ty| {
+ tcx.mk_const(ty::PlaceholderConst { universe, bound: bv }, ty)
+ },
+ },
+ );
- 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 = ocx.normalize(&cause, param_env, impl_ty);
+ candidates
+ .iter()
+ .filter_map(|&(impl_, (assoc_item, def_scope))| {
+ infcx.probe(|_| {
+ let ocx = ObligationCtxt::new_in_snapshot(&infcx);
- // 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()?;
+ 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 = ocx.normalize(&cause, param_env, impl_ty);
- // 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);
+ // 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()?;
- let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
+ // 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_obligations = traits::predicates_for_generics(
- |_, _| cause.clone(),
- param_env,
- impl_bounds,
- );
+ let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
- ocx.register_obligations(impl_obligations);
+ let impl_obligations = traits::predicates_for_generics(
+ |_, _| cause.clone(),
+ param_env,
+ impl_bounds,
+ );
- let mut errors = ocx.select_where_possible();
- if !errors.is_empty() {
- fulfillment_errors.append(&mut errors);
- return None;
- }
+ ocx.register_obligations(impl_obligations);
+
+ let mut errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ fulfillment_errors.append(&mut errors);
+ return None;
+ }
- // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot.
- Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs)))
+ // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot.
+ Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs)))
+ })
})
- })
- .collect();
+ .collect()
+ });
if applicable_candidates.len() > 1 {
return Err(self.complain_about_ambiguous_inherent_assoc_type(
@@ -2396,13 +2520,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx,
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
);
+ let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
+ // FIXME: Don't bother dealing with non-lifetime binders here...
+ if value.has_escaping_bound_vars() {
+ return false;
+ }
infcx
.can_eq(
ty::ParamEnv::empty(),
impl_.self_ty(),
- // Must fold past escaping bound vars too,
- // since we have those at this point in astconv.
- tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
+ value,
)
})
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
@@ -2451,7 +2578,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.all_impls(trait_def_id)
.filter(|impl_def_id| {
// Consider only accessible traits
- tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx)
+ tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
})
.filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
@@ -2596,7 +2723,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for segment in segments {
// Only emit the first error to avoid overloading the user with error messages.
if let Some(b) = segment.args().bindings.first() {
- prohibit_assoc_ty_binding(self.tcx(), b.span);
+ prohibit_assoc_ty_binding(self.tcx(), b.span, None);
return true;
}
}
@@ -3049,10 +3176,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
- let def_id = item_id.owner_id.to_def_id();
match opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
+ let local_def_id = item_id.owner_id.def_id;
+ // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
+ // generate the def_id of an associated type for the trait and return as
+ // type a projection.
+ let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+ tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id()
+ } else {
+ local_def_id.to_def_id()
+ };
self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait)
}
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
@@ -3133,8 +3268,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("impl_trait_ty_to_ty: generics={:?}", generics);
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
- if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
- // Our own parameters are the resolved lifetimes.
+ // We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
+ // since return-position impl trait in trait squashes all of the generics from its source fn
+ // into its own generics, so the opaque's "own" params isn't always just lifetimes.
+ if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len())
+ {
+ // Resolve our own lifetime parameters.
let GenericParamDefKind::Lifetime { .. } = param.kind else { bug!() };
let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { bug!() };
self.ast_region_to_region(lifetime, None).into()
@@ -3309,10 +3448,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx,
trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
);
+ let fn_sig = tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), fn_sig);
- let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
-
- Some(tcx.liberate_late_bound_regions(fn_hir_id.expect_owner().to_def_id(), ty))
+ Some(if let Some(arg_idx) = arg_idx {
+ *fn_sig.inputs().get(arg_idx)?
+ } else {
+ fn_sig.output()
+ })
}
#[instrument(level = "trace", skip(self, generate_err))]
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 0880c8c15..284b099e7 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -58,7 +58,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]));
- // Preferrable to put this obligation first, since we report better errors for sized ambiguity.
+ // 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 848828175..0bb98fdf2 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,5 +1,5 @@
use crate::check::intrinsicck::InlineAsmCtxt;
-use crate::errors::LinkageType;
+use crate::errors::{self, LinkageType};
use super::compare_impl_item::check_type_bounds;
use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
@@ -22,12 +22,12 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{
- self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
- TypeVisitableExt,
+ self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
+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 _;
@@ -115,9 +115,11 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
allowed_union_field(*elem, tcx, param_env)
}
_ => {
- // Fallback case: allow `ManuallyDrop` and things that are `Copy`.
+ // Fallback case: allow `ManuallyDrop` and things that are `Copy`,
+ // also no need to report an error if the type is unresolved.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
|| ty.is_copy_modulo_regions(tcx, param_env)
+ || ty.references_error()
}
}
}
@@ -132,26 +134,14 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
Some(Node::Field(field)) => (field.span, field.ty.span),
_ => unreachable!("mir field has to correspond to hir field"),
};
- struct_span_err!(
- tcx.sess,
+ tcx.sess.emit_err(errors::InvalidUnionField {
field_span,
- E0740,
- "unions cannot contain fields that may need dropping"
- )
- .note(
- "a type is guaranteed not to need dropping \
- when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type",
- )
- .multipart_suggestion_verbose(
- "when the type does not implement `Copy`, \
- wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped",
- vec![
- (ty_span.shrink_to_lo(), "std::mem::ManuallyDrop<".into()),
- (ty_span.shrink_to_hi(), ">".into()),
- ],
- Applicability::MaybeIncorrect,
- )
- .emit();
+ sugg: errors::InvalidUnionFieldSuggestion {
+ lo: ty_span.shrink_to_lo(),
+ hi: ty_span.shrink_to_hi(),
+ },
+ note: (),
+ });
return false;
} else if field_ty.needs_drop(tcx, param_env) {
// This should never happen. But we can get here e.g. in case of name resolution errors.
@@ -222,7 +212,7 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
return;
}
- let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, item.owner_id);
let span = tcx.def_span(item.owner_id.def_id);
if !tcx.features().impl_trait_projections {
@@ -315,8 +305,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
..
}) = item.kind
{
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- let opaque_identity_ty = if in_trait {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
tcx.mk_projection(def_id.to_def_id(), substs)
} else {
tcx.mk_opaque(def_id.to_def_id(), substs)
@@ -455,18 +445,15 @@ fn check_opaque_meets_bounds<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
match origin {
// Checked when type checking the function containing them.
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias => {
- let outlives_environment = OutlivesEnvironment::new(param_env);
- let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(
- defining_use_anchor,
- &outlives_environment,
- );
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
}
}
// Clean up after ourselves
@@ -485,7 +472,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
let [var_one, var_two] = &adt_def.variants().raw[..] else {
return false;
};
- let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
+ let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
return false;
};
matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
@@ -546,7 +533,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
}
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
let trait_substs =
- InternalSubsts::identity_for_item(tcx, id.owner_id.to_def_id());
+ InternalSubsts::identity_for_item(tcx, id.owner_id);
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
@@ -565,10 +552,18 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_union(tcx, id.owner_id.def_id);
}
DefKind::OpaqueTy => {
- check_opaque(tcx, id);
+ let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
+ if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+ && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
+ && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
+ {
+ // Skip opaques from RPIT in traits with no default body.
+ } else {
+ check_opaque(tcx, id);
+ }
}
DefKind::ImplTraitPlaceholder => {
- let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
+ let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
// Only check the validity of this opaque type if the function has a default body
if let hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
@@ -896,7 +891,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
- let e = fields[0].ty(tcx, substs);
+ let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
.span_label(sp, "SIMD elements must have the same type")
@@ -1172,7 +1167,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
def.destructor(tcx); // force the destructor to be evaluated
if def.variants().is_empty() {
- if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() {
+ if let Some(attr) = tcx.get_attrs(def_id, sym::repr).next() {
struct_span_err!(
tcx.sess,
attr.span,
@@ -1511,6 +1506,14 @@ fn opaque_type_cycle_error(
{
label_match(interior_ty.ty, interior_ty.span);
}
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir
+ && let DefKind::Generator = tcx.def_kind(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);
+ }
+ }
}
}
}
@@ -1548,6 +1551,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let errors = fulfillment_cx.select_all_or_error(&infcx);
debug!(?errors);
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
}
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 691d3f8d9..5d119a773 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -16,8 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{
- self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
- TypeVisitableExt,
+ self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::Span;
@@ -321,7 +320,7 @@ fn compare_method_predicate_entailment<'tcx>(
});
}
CheckImpliedWfMode::Skip => {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
}
@@ -331,13 +330,8 @@ fn compare_method_predicate_entailment<'tcx>(
// lifetime parameters.
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
- Some(infcx),
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
);
- infcx.process_registered_region_obligations(
- outlives_env.region_bound_pairs(),
- outlives_env.param_env,
- );
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() {
// FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
@@ -584,13 +578,13 @@ fn compare_asyncness<'tcx>(
#[instrument(skip(tcx), level = "debug", ret)]
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ impl_m_def_id: LocalDefId,
) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
- let impl_m = tcx.opt_associated_item(def_id).unwrap();
+ 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 =
tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity();
- let param_env = tcx.param_env(def_id);
+ let param_env = tcx.param_env(impl_m_def_id);
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
@@ -600,7 +594,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let trait_to_impl_substs = impl_trait_ref.substs;
- let impl_m_def_id = impl_m.def_id.expect_local();
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
let cause = ObligationCause::new(
@@ -721,23 +714,22 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// RPITs.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
+ let collected_types = collector.types;
+
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
- let outlives_environment = OutlivesEnvironment::with_bounds(
+ let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
- Some(infcx),
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
);
- infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?;
+ ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
let mut collected_tys = FxHashMap::default();
- for (def_id, (ty, substs)) in collector.types {
+ for (def_id, (ty, substs)) in collected_types {
match infcx.fully_resolve(ty) {
Ok(ty) => {
// `ty` contains free regions that we created earlier while liberating the
@@ -831,7 +823,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Alias(ty::Projection, proj) = ty.kind()
- && self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+ && self.interner().is_impl_trait_in_trait(proj.def_id)
{
if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
@@ -1206,6 +1198,17 @@ fn compare_number_of_generics<'tcx>(
return Ok(());
}
+ // We never need to emit a separate error for RPITITs, since if an RPITIT
+ // has mismatched type or const generic arguments, then the method that it's
+ // inheriting the generics from will also have mismatched arguments, and
+ // we'll report an error for that instead. Delay a bug for safety, though.
+ if tcx.opt_rpitit_info(trait_.def_id).is_some() {
+ return Err(tcx.sess.delay_span_bug(
+ rustc_span::DUMMY_SP,
+ "errors comparing numbers of generics of trait/impl functions were not emitted",
+ ));
+ }
+
let matchings = [
("type", trait_own_counts.types, impl_own_counts.types),
("const", trait_own_counts.consts, impl_own_counts.consts),
@@ -1732,14 +1735,11 @@ pub(super) fn compare_impl_const_raw(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
+ return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
}
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;
- Ok(())
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
}
pub(super) fn compare_impl_ty<'tcx>(
@@ -1832,19 +1832,14 @@ fn compare_type_predicate_entailment<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx.err_ctxt().check_region_obligations_and_report_errors(
- impl_ty.def_id.expect_local(),
- &outlives_environment,
- )?;
-
- Ok(())
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
}
/// Validate that `ProjectionCandidate`s created for this associated type will
@@ -1867,14 +1862,17 @@ pub(super) fn check_type_bounds<'tcx>(
impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
+ let param_env = tcx.param_env(impl_ty.def_id);
+ let container_id = impl_ty.container_id(tcx);
// Given
//
// impl<A, B> Foo<u32> for (A, B) {
- // type Bar<C> =...
+ // type Bar<C> = Wrapper<A, B, C>
// }
//
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
- // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+ // - `normalize_impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+ // - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
// - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
// the *trait* with the generic associated type parameters (as bound vars).
//
@@ -1903,56 +1901,46 @@ pub(super) fn check_type_bounds<'tcx>(
// Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing
// elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in
// the trait (notably, that X: Eq and T: Family).
- let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id);
- let mut substs = smallvec::SmallVec::with_capacity(defs.count());
- if let Some(def_id) = defs.parent {
- let parent_defs = tcx.generics_of(def_id);
- InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| {
- tcx.mk_param_from_def(param)
- });
- }
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
- smallvec::SmallVec::with_capacity(defs.count());
- InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
- GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.def_id, param.name);
- let bound_var = ty::BoundVariableKind::Ty(kind);
- bound_vars.push(bound_var);
- tcx.mk_bound(
- ty::INNERMOST,
- ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
- )
- .into()
- }
- GenericParamDefKind::Lifetime => {
- let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
- let bound_var = ty::BoundVariableKind::Region(kind);
- bound_vars.push(bound_var);
- tcx.mk_re_late_bound(
- ty::INNERMOST,
- ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
- )
- .into()
- }
- GenericParamDefKind::Const { .. } => {
- let bound_var = ty::BoundVariableKind::Const;
- bound_vars.push(bound_var);
- tcx.mk_const(
- ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1)),
- tcx.type_of(param.def_id).subst_identity(),
- )
- .into()
- }
- });
- let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
- let impl_ty_substs = tcx.mk_substs(&substs);
- let container_id = impl_ty.container_id(tcx);
-
- let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
- let impl_ty_value = tcx.type_of(impl_ty.def_id).subst_identity();
-
- let param_env = tcx.param_env(impl_ty.def_id);
-
+ smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
+ // Extend the impl's identity substs with late-bound GAT vars
+ let normalize_impl_ty_substs = ty::InternalSubsts::identity_for_item(tcx, container_id)
+ .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
+ GenericParamDefKind::Type { .. } => {
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Ty(kind);
+ bound_vars.push(bound_var);
+ tcx.mk_bound(
+ ty::INNERMOST,
+ ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+ )
+ .into()
+ }
+ GenericParamDefKind::Lifetime => {
+ let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Region(kind);
+ bound_vars.push(bound_var);
+ tcx.mk_re_late_bound(
+ ty::INNERMOST,
+ ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+ )
+ .into()
+ }
+ GenericParamDefKind::Const { .. } => {
+ let bound_var = ty::BoundVariableKind::Const;
+ bound_vars.push(bound_var);
+ tcx.mk_const(
+ ty::ConstKind::Bound(
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(bound_vars.len() - 1),
+ ),
+ tcx.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into()
+ }
+ });
// When checking something like
//
// trait X { type Y: PartialEq<<Self as X>::Y> }
@@ -1962,9 +1950,13 @@ pub(super) fn check_type_bounds<'tcx>(
// we want <T as X>::Y to normalize to S. This is valid because we are
// checking the default value specifically here. Add this equality to the
// ParamEnv for normalization specifically.
+ let normalize_impl_ty = tcx.type_of(impl_ty.def_id).subst(tcx, normalize_impl_ty_substs);
+ let rebased_substs =
+ normalize_impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+ let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
- match impl_ty_value.kind() {
+ match normalize_impl_ty.kind() {
ty::Alias(ty::Projection, proj)
if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
{
@@ -1978,7 +1970,7 @@ pub(super) fn check_type_bounds<'tcx>(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
- term: impl_ty_value.into(),
+ term: normalize_impl_ty.into(),
},
bound_vars,
)
@@ -1996,13 +1988,20 @@ pub(super) fn check_type_bounds<'tcx>(
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
- let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
- hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Type(_, Some(ty)),
- ..
- }) => ty.span,
- hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
- _ => bug!(),
+ // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
+ // span for an impl's associated type. Instead, for these, use the def_span for the synthesized
+ // associated type.
+ let impl_ty_span = if tcx.opt_rpitit_info(impl_ty.def_id).is_some() {
+ tcx.def_span(impl_ty_def_id)
+ } else {
+ match tcx.hir().get_by_def_id(impl_ty_def_id) {
+ hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Type(_, Some(ty)),
+ ..
+ }) => ty.span,
+ hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
+ _ => bug!(),
+ }
};
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
@@ -2023,7 +2022,7 @@ pub(super) fn check_type_bounds<'tcx>(
ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
};
- let obligations = tcx
+ let obligations: Vec<_> = tcx
.bound_explicit_item_bounds(trait_ty.def_id)
.subst_iter_copied(tcx, rebased_substs)
.map(|(concrete_ty_bound, span)| {
@@ -2033,7 +2032,7 @@ pub(super) fn check_type_bounds<'tcx>(
.collect();
debug!("check_type_bounds: item_bounds={:?}", obligations);
- for mut obligation in util::elaborate_obligations(tcx, obligations) {
+ for mut obligation in util::elaborate(tcx, obligations) {
let normalized_predicate =
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
@@ -2045,22 +2044,15 @@ pub(super) fn check_type_bounds<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
- let outlives_environment =
- OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
-
- infcx.err_ctxt().check_region_obligations_and_report_errors(
- impl_ty.def_id.expect_local(),
- &outlives_environment,
- )?;
-
- Ok(())
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+ ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
}
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 2bb724138..111bf5e54 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -253,10 +253,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
self.tcx
}
- fn intercrate(&self) -> bool {
- false
- }
-
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
@@ -269,10 +265,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
true
}
- fn mark_ambiguous(&mut self) {
- bug!()
- }
-
fn relate_with_variance<T: Relate<'tcx>>(
&mut self,
_: ty::Variance,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 054284cce..854974d16 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -59,6 +59,7 @@ fn equate_intrinsic_type<'tcx>(
require_same_types(
tcx,
&cause,
+ ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()),
fty,
);
@@ -138,14 +139,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let name_str = intrinsic_name.as_str();
let bound_vars = tcx.mk_bound_variable_kinds(&[
- ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+ ty::BoundVariableKind::Region(ty::BrAnon(None)),
ty::BoundVariableKind::Region(ty::BrEnv),
]);
let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| {
let region = tcx.mk_re_late_bound(
ty::INNERMOST,
- ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
+ ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
);
let env_region = tcx.mk_re_late_bound(
ty::INNERMOST,
@@ -222,6 +223,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
),
+ sym::option_payload_ptr => {
+ let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None);
+ let p0 = param(0);
+ (
+ 1,
+ vec![tcx.mk_ptr(ty::TypeAndMut {
+ ty: tcx.mk_adt(
+ tcx.adt_def(option_def_id),
+ tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()),
+ ),
+ mutbl: hir::Mutability::Not,
+ })],
+ tcx.mk_ptr(ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }),
+ )
+ }
sym::ptr_mask => (
1,
vec![
@@ -300,6 +316,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+ sym::roundevenf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+ sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::volatile_load | sym::unaligned_volatile_load => {
(1, vec![tcx.mk_imm_ptr(param(0))], param(0))
@@ -361,14 +379,15 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
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::discriminant_value => {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
let discriminant_def_id = assoc_items[0];
- let br =
- ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+ let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
(
1,
vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
@@ -420,8 +439,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
sym::raw_eq => {
- let br =
- ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+ let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
(1, vec![param_ty; 2], tcx.types.bool)
}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index b1d5a27be..0d482b53a 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,10 +1,11 @@
use rustc_ast::InlineAsmTemplatePiece;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, DUMMY_SP};
+use rustc_target::abi::FieldIdx;
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
pub struct InlineAsmCtxt<'a, 'tcx> {
@@ -51,7 +52,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
template: &[InlineAsmTemplatePiece],
is_input: bool,
tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>,
- target_features: &FxHashSet<Symbol>,
+ target_features: &FxIndexSet<Symbol>,
) -> Option<InlineAsmType> {
let ty = (self.get_operand_ty)(expr);
if ty.has_non_region_infer() {
@@ -82,7 +83,7 @@ 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[0].ty(self.tcx, substs);
+ 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) => {
@@ -201,7 +202,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// (!). In that case we still need the earlier check to verify that the
// register class is usable at all.
if let Some(feature) = feature {
- if !target_features.contains(&feature) {
+ if !target_features.contains(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!(
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 9acfc1b3d..8fe4c44fc 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -109,8 +109,8 @@ pub fn provide(providers: &mut Providers) {
};
}
-fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
- tcx.calculate_dtor(def_id, dropck::check_drop_impl)
+fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
+ tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
}
/// Given a `DefId` for an opaque type in return position, find its parent item's return
@@ -202,8 +202,11 @@ fn missing_items_err(
missing_items: &[ty::AssocItem],
full_impl_span: Span,
) {
+ let missing_items =
+ missing_items.iter().filter(|trait_item| tcx.opt_rpitit_info(trait_item.def_id).is_none());
+
let missing_items_msg = missing_items
- .iter()
+ .clone()
.map(|trait_item| trait_item.name.to_string())
.collect::<Vec<_>>()
.join("`, `");
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 4cccdf30c..53197bc84 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
-use hir::def::DefKind;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -111,16 +110,13 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
let errors = wfcx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
return;
}
- let outlives_environment =
- OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
- let _ = infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
+ let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env);
}
fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
@@ -676,19 +672,13 @@ fn resolve_regions_with_wf_tys<'tcx>(
let infcx = tcx.infer_ctxt().build();
let outlives_environment = OutlivesEnvironment::with_bounds(
param_env,
- Some(&infcx),
infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
);
let region_bound_pairs = outlives_environment.region_bound_pairs();
add_constraints(&infcx, region_bound_pairs);
- infcx.process_registered_region_obligations(
- outlives_environment.region_bound_pairs(),
- param_env,
- );
let errors = infcx.resolve_regions(&outlives_environment);
-
debug!(?errors, "errors");
// If we were able to prove that the type outlives the region without
@@ -1033,7 +1023,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.fields.last().unwrap().did).subst_identity();
+ let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
let ty = tcx.erase_regions(ty);
if ty.needs_infer() {
tcx.sess
@@ -1049,7 +1039,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
let unsized_len = if all_sized { 0 } else { 1 };
for (idx, field) in
- variant.fields[..variant.fields.len() - unsized_len].iter().enumerate()
+ variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
{
let last = idx == variant.fields.len() - 1;
let field_id = field.did.expect_local();
@@ -1545,31 +1535,81 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
span: Span,
) {
let tcx = wfcx.tcx();
- if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
- && assoc_item.container == ty::AssocItemContainer::TraitContainer
- {
- for arg in fn_output.walk() {
- if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Opaque, proj) = ty.kind()
- && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
- && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
+ let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
+ return;
+ };
+ if assoc_item.container != ty::AssocItemContainer::TraitContainer {
+ return;
+ }
+ fn_output.visit_with(&mut ImplTraitInTraitFinder {
+ wfcx,
+ fn_def_id,
+ depth: ty::INNERMOST,
+ seen: FxHashSet::default(),
+ });
+}
+
+// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
+// strategy, we can't just call `check_associated_item` on the new RPITITs,
+// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
+// That's because we need to check that the bounds of the RPITIT hold using
+// the special substs that we create during opaque type lowering, otherwise we're
+// getting a bunch of early bound and free regions mixed up... Haven't looked too
+// deep into this, though.
+struct ImplTraitInTraitFinder<'a, 'tcx> {
+ wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
+ fn_def_id: LocalDefId,
+ depth: ty::DebruijnIndex,
+ seen: FxHashSet<DefId>,
+}
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
+ type BreakTy = !;
+
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
+ let tcx = self.wfcx.tcx();
+ if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
+ && self.seen.insert(unshifted_opaque_ty.def_id)
+ && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
+ && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
+ && 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
+ }
+ });
+ for (bound, bound_span) in tcx
+ .bound_explicit_item_bounds(opaque_ty.def_id)
+ .subst_iter_copied(tcx, opaque_ty.substs)
{
- let span = tcx.def_span(proj.def_id);
- let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
- let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
- let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
- let normalized_bound = wfcx.normalize(span, None, bound);
- traits::wf::predicate_obligations(
- wfcx.infcx,
- wfcx.param_env,
- wfcx.body_def_id,
- normalized_bound,
- bound_span,
- )
- });
- wfcx.register_obligations(wf_obligations);
+ let bound = self.wfcx.normalize(bound_span, None, bound);
+ self.wfcx.register_obligations(traits::wf::predicate_obligations(
+ self.wfcx.infcx,
+ self.wfcx.param_env,
+ self.wfcx.body_def_id,
+ bound,
+ bound_span,
+ ));
+ // Set the debruijn index back to innermost here, since we already eagerly
+ // shifted the substs that we use to generate these bounds. This is unfortunately
+ // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
+ // but that function doesn't actually need to normalize the bound it's visiting
+ // (whereas we have to do so here)...
+ let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
+ bound.visit_with(self);
+ self.depth = old_depth;
}
}
+ ty.super_visit_with(self)
}
}
@@ -1784,7 +1824,7 @@ fn check_variances_for_type_defn<'tcx>(
// Lazily calculated because it is only needed in case of an error.
let explicitly_bounded_params = LazyCell::new(|| {
- let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id());
+ let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.def_id);
hir_generics
.predicates
.iter()
@@ -1861,16 +1901,15 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
// Check elaborated bounds.
- let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
+ let implied_obligations = traits::elaborate(tcx, predicates_with_span);
- for obligation in implied_obligations {
+ for (pred, obligation_span) in implied_obligations {
// We lower empty bounds like `Vec<dyn Copy>:` as
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
// regular WF checking
- if let ty::PredicateKind::WellFormed(..) = obligation.predicate.kind().skip_binder() {
+ if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() {
continue;
}
- let pred = obligation.predicate;
// Match the existing behavior.
if pred.is_global() && !pred.has_late_bound_vars() {
let pred = self.normalize(span, None, pred);
@@ -1881,8 +1920,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
if let Some(hir::Generics { predicates, .. }) =
hir_node.and_then(|node| node.generics())
{
- let obligation_span = obligation.cause.span();
-
span = predicates
.iter()
// There seems to be no better way to find out which predicate we are in
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index f3f5851d8..268b9ac53 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -10,7 +10,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
for item_def_id in tcx.hir().body_owners() {
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
- used_trait_imports.extend(imports.items().copied());
+ used_trait_imports.extend_unord(imports.items().copied());
}
for &id in tcx.maybe_unused_trait_imports(()) {
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index ffb68abf9..0f40cca94 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -2,21 +2,23 @@
//! up data structures required by type-checking/codegen.
use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{self, RegionResolutionError};
+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_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
};
-use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCause};
use std::collections::BTreeMap;
@@ -86,7 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
tcx.sess,
span,
E0204,
- "the trait `Copy` may not be implemented for this type"
+ "the trait `Copy` cannot be implemented for this type"
);
// We'll try to suggest constraining type parameters to fulfill the requirements of
@@ -94,7 +96,14 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
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`");
@@ -227,7 +236,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
use rustc_type_ir::sty::TyKind::*;
match (source.kind(), target.kind()) {
(&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
- if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {}
+ if infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, r_a, *r_b).is_ok()
+ && mutbl_a == *mutbl_b => {}
(&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
(&Adt(def_a, substs_a), &Adt(def_b, substs_b))
if def_a.is_struct() && def_b.is_struct() =>
@@ -270,7 +280,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
}
- if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
+ if let Ok(ok) =
+ infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
+ {
if ok.obligations.is_empty() {
create_err(
"the trait `DispatchFromDyn` may only be implemented \
@@ -323,28 +335,26 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
))
.emit();
} else {
- let errors = traits::fully_solve_obligations(
- &infcx,
- coerced_fields.into_iter().map(|field| {
- predicate_for_trait_def(
- tcx,
- param_env,
- cause.clone(),
+ let ocx = ObligationCtxt::new(&infcx);
+ for field in coerced_fields {
+ ocx.register_obligation(Obligation::new(
+ tcx,
+ cause.clone(),
+ param_env,
+ ty::Binder::dummy(tcx.mk_trait_ref(
dispatch_from_dyn_trait,
- 0,
[field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
- )
- }),
- );
+ )),
+ ));
+ }
+ let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
- let _ = infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(impl_did, &outlives_env);
+ let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
}
}
_ => {
@@ -357,11 +367,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
}
-pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
+pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> CoerceUnsizedInfo {
debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
-
- // this provider should only get invoked for local def-ids
- let impl_did = impl_did.expect_local();
let span = tcx.def_span(impl_did);
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
@@ -477,8 +484,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
// U` can be coerced to `*mut V` if `U: Unsize<V>`.
let fields = &def_a.non_enum_variant().fields;
let diff_fields = fields
- .iter()
- .enumerate()
+ .iter_enumerated()
.filter_map(|(i, f)| {
let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
@@ -496,7 +502,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
// we may have to evaluate constraint
// expressions in the course of execution.)
// See e.g., #41936.
- if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
+ if let Ok(ok) = infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, a, b) {
if ok.obligations.is_empty() {
return None;
}
@@ -572,17 +578,19 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
};
// Register an obligation for `A: Trait<B>`.
+ let ocx = ObligationCtxt::new(&infcx);
let cause = traits::ObligationCause::misc(span, impl_did);
- let predicate =
- predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
- let errors = traits::fully_solve_obligation(&infcx, predicate);
+ let obligation =
+ Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target]));
+ ocx.register_obligation(obligation);
+ let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
// Finally, resolve all regions.
let outlives_env = OutlivesEnvironment::new(param_env);
- let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env);
+ let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
CoerceUnsizedInfo { custom_kind: kind }
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 02f3eeee0..3d37e0ce0 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -10,7 +10,7 @@
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::symbol::sym;
@@ -24,7 +24,7 @@ pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
collect.impls_map
}
-pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedType)) -> &[DefId] {
+pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
let crate_map = tcx.crate_inherent_impls(());
tcx.arena.alloc_from_iter(
crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
@@ -32,9 +32,7 @@ pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedT
}
/// On-demand query: yields a vector of the inherent impls for a specific type.
-pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
- let ty_def_id = ty_def_id.expect_local();
-
+pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
let crate_map = tcx.crate_inherent_impls(());
match crate_map.inherent_impls.get(&ty_def_id) {
Some(v) => &v[..],
@@ -99,7 +97,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
}
- if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
+ if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
@@ -159,7 +157,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
}
- if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) {
+ if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected primitive type: {:?}", ty);
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 7bca4edcc..ad76e2bed 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -302,7 +302,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
.iter()
.flatten()
.map(|r| r.impl_blocks.len() as isize - avg as isize)
- .map(|v| v.abs() as usize)
+ .map(|v| v.unsigned_abs())
.sum::<usize>();
s / connected_regions.len()
},
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 23490bc09..465e787c9 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -133,8 +133,8 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
check_impl(tcx, impl_def_id, trait_ref);
check_object_overlap(tcx, impl_def_id, trait_ref);
- tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id));
- tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id));
+ unsafety::check_item(tcx, impl_def_id);
+ tcx.ensure().orphan_check_impl(impl_def_id);
}
builtin::check_trait(tcx, def_id);
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 1f2de3f21..47c47de8c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -478,10 +478,6 @@ fn lint_auto_trait_impl<'tcx>(
trait_ref: ty::TraitRef<'tcx>,
impl_def_id: LocalDefId,
) {
- if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
- return;
- }
-
assert_eq!(trait_ref.substs.len(), 1);
let self_ty = trait_ref.self_ty();
let (self_type_did, substs) = match self_ty.kind() {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 604d54caf..cbbaf8f85 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -20,7 +20,7 @@ use crate::errors;
use hir::def::DefKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
@@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
predicates_defined_on,
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,
trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
@@ -113,7 +114,7 @@ pub fn provide(providers: &mut Providers) {
/// the AST (`hir::Generics`), recursively.
pub struct ItemCtxt<'tcx> {
tcx: TyCtxt<'tcx>,
- item_def_id: DefId,
+ item_def_id: LocalDefId,
}
///////////////////////////////////////////////////////////////////////////
@@ -333,21 +334,11 @@ fn bad_placeholder<'tcx>(
let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
spans.sort();
- let mut err = struct_span_err!(
- tcx.sess,
- spans.clone(),
- E0121,
- "the placeholder `_` is not allowed within types on item signatures for {}",
- kind
- );
- for span in spans {
- err.span_label(span, "not allowed in type signatures");
- }
- err
+ tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
}
impl<'tcx> ItemCtxt<'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> {
+ pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
ItemCtxt { tcx, item_def_id }
}
@@ -356,7 +347,7 @@ impl<'tcx> ItemCtxt<'tcx> {
}
pub fn hir_id(&self) -> hir::HirId {
- self.tcx.hir().local_def_id_to_hir_id(self.item_def_id.expect_local())
+ self.tcx.hir().local_def_id_to_hir_id(self.item_def_id)
}
pub fn node(&self) -> hir::Node<'tcx> {
@@ -370,20 +361,16 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
}
fn item_def_id(&self) -> DefId {
- self.item_def_id
+ self.item_def_id.to_def_id()
}
fn get_type_parameter_bounds(
&self,
span: Span,
- def_id: DefId,
+ def_id: LocalDefId,
assoc_name: Ident,
) -> ty::GenericPredicates<'tcx> {
- self.tcx.at(span).type_param_predicates((
- self.item_def_id,
- def_id.expect_local(),
- assoc_name,
- ))
+ self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name))
}
fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
@@ -423,13 +410,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
self.tcx().mk_projection(item_def_id, item_substs)
} else {
// There are no late-bound regions; we can just ignore the binder.
- let mut err = struct_span_err!(
- self.tcx().sess,
- span,
- E0212,
- "cannot use the associated type of a trait \
- with uninferred generic parameters"
- );
+ let (mut mpart_sugg, mut inferred_sugg) = (None, None);
+ let mut bound = String::new();
match self.node() {
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
@@ -448,31 +430,25 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
(bound.span.shrink_to_lo(), format!("{}, ", lt_name))
}
};
- let suggestions = vec![
- (lt_sp, sugg),
- (
- span.with_hi(item_segment.ident.span.lo()),
- format!(
- "{}::",
- // Replace the existing lifetimes with a new named lifetime.
- self.tcx.replace_late_bound_regions_uncached(
- poly_trait_ref,
- |_| {
- self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: item_def_id,
- index: 0,
- name: Symbol::intern(&lt_name),
- })
- }
- ),
+ mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+ fspan: lt_sp,
+ first: sugg,
+ sspan: span.with_hi(item_segment.ident.span.lo()),
+ second: format!(
+ "{}::",
+ // Replace the existing lifetimes with a new named lifetime.
+ self.tcx.replace_late_bound_regions_uncached(
+ poly_trait_ref,
+ |_| {
+ self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ def_id: item_def_id,
+ index: 0,
+ name: Symbol::intern(&lt_name),
+ })
+ }
),
),
- ];
- err.multipart_suggestion(
- "use a fully qualified path with explicit lifetimes",
- suggestions,
- Applicability::MaybeIncorrect,
- );
+ });
}
_ => {}
}
@@ -486,20 +462,23 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
| hir::Node::ForeignItem(_)
| hir::Node::TraitItem(_)
| hir::Node::ImplItem(_) => {
- err.span_suggestion_verbose(
- span.with_hi(item_segment.ident.span.lo()),
- "use a fully qualified path with inferred lifetimes",
- format!(
- "{}::",
- // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
- self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
- ),
- Applicability::MaybeIncorrect,
+ inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
+ bound = format!(
+ "{}::",
+ // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
+ self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
);
}
_ => {}
}
- self.tcx().ty_error(err.emit())
+ self.tcx().ty_error(self.tcx().sess.emit_err(
+ errors::AssociatedTypeTraitUninferredGenericParams {
+ span,
+ inferred_sugg,
+ bound,
+ mpart_sugg,
+ },
+ ))
}
}
@@ -618,6 +597,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
}
hir::ItemKind::TraitAlias(..) => {
tcx.ensure().generics_of(def_id);
+ tcx.at(it.span).implied_predicates_of(def_id);
tcx.at(it.span).super_predicates_of(def_id);
tcx.ensure().predicates_of(def_id);
}
@@ -767,14 +747,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
Some(discr)
} else {
let span = tcx.def_span(variant.def_id);
- struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed")
- .span_label(span, format!("overflowed on value after {}", prev_discr.unwrap()))
- .note(&format!(
- "explicitly set `{} = {}` if that is desired outcome",
- tcx.item_name(variant.def_id),
- wrapped_discr
- ))
- .emit();
+ tcx.sess.emit_err(errors::EnumDiscriminantOverflowed {
+ span,
+ discr: prev_discr.unwrap().to_string(),
+ item_name: tcx.item_name(variant.def_id),
+ wrapped_discr: wrapped_discr.to_string(),
+ });
None
}
.unwrap_or(wrapped_discr),
@@ -839,17 +817,15 @@ fn convert_variant(
adt_kind,
parent_did.to_def_id(),
recovered,
- adt_kind == AdtKind::Struct && tcx.has_attr(parent_did.to_def_id(), sym::non_exhaustive)
- || variant_did.map_or(false, |variant_did| {
- tcx.has_attr(variant_did.to_def_id(), sym::non_exhaustive)
- }),
+ 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)),
)
}
-fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> {
+fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
use rustc_hir::*;
- let def_id = def_id.expect_local();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let Node::Item(item) = tcx.hir().get(hir_id) else {
bug!();
@@ -908,8 +884,8 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> {
tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
}
-fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
- let item = tcx.hir().expect_item(def_id.expect_local());
+fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
+ let item = tcx.hir().expect_item(def_id);
let (is_auto, unsafety, items) = match item.kind {
hir::ItemKind::Trait(is_auto, unsafety, .., items) => {
@@ -921,14 +897,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
if paren_sugar && !tcx.features().unboxed_closures {
- tcx.sess
- .struct_span_err(
- item.span,
- "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")
- .emit();
+ tcx.sess.emit_err(errors::ParenSugarAttribute { span: item.span });
}
let is_marker = tcx.has_attr(def_id, sym::marker);
@@ -948,13 +917,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
// and that they are all identifiers
.and_then(|attr| match attr.meta_item_list() {
Some(items) if items.len() < 2 => {
- tcx.sess
- .struct_span_err(
- attr.span,
- "the `#[rustc_must_implement_one_of]` attribute must be \
- used with at least 2 args",
- )
- .emit();
+ tcx.sess.emit_err(errors::MustImplementOneOfAttribute { span: attr.span });
None
}
@@ -963,9 +926,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
.map(|item| item.ident().ok_or(item.span()))
.collect::<Result<Box<[_]>, _>>()
.map_err(|span| {
- tcx.sess
- .struct_span_err(span, "must be a name of an associated function")
- .emit();
+ tcx.sess.emit_err(errors::MustBeNameOfAssociatedFunction { span });
})
.ok()
.zip(Some(attr.span)),
@@ -981,13 +942,10 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
match item {
Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
if !tcx.impl_defaultness(item.id.owner_id).has_value() {
- tcx.sess
- .struct_span_err(
- item.span,
- "function doesn't have a default implementation",
- )
- .span_note(attr_span, "required by this annotation")
- .emit();
+ tcx.sess.emit_err(errors::FunctionNotHaveDefaultImplementation {
+ span: item.span,
+ note_span: attr_span,
+ });
return Some(());
}
@@ -995,19 +953,14 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
return None;
}
Some(item) => {
- tcx.sess
- .struct_span_err(item.span, "not a function")
- .span_note(attr_span, "required by this annotation")
- .note(
- "all `#[rustc_must_implement_one_of]` arguments must be associated \
- function names",
- )
- .emit();
+ tcx.sess.emit_err(errors::MustImplementNotFunction {
+ span: item.span,
+ span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
+ note: errors::MustImplementNotFunctionNote {},
+ });
}
None => {
- tcx.sess
- .struct_span_err(ident.span, "function not found in this trait")
- .emit();
+ tcx.sess.emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
}
}
@@ -1024,9 +977,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
for ident in &*list {
if let Some(dup) = set.insert(ident.name, ident.span) {
tcx.sess
- .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
- .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
- .emit();
+ .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
no_dups = false;
}
@@ -1036,7 +987,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
});
ty::TraitDef {
- def_id,
+ def_id: def_id.to_def_id(),
unsafety,
paren_sugar,
has_auto_impl: is_auto,
@@ -1091,14 +1042,13 @@ pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir
}
#[instrument(level = "debug", skip(tcx))]
-fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> {
+fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> {
use rustc_hir::Node::*;
use rustc_hir::*;
- let def_id = def_id.expect_local();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let icx = ItemCtxt::new(tcx, def_id.to_def_id());
+ let icx = ItemCtxt::new(tcx, def_id);
let output = match tcx.hir().get(hir_id) {
TraitItem(hir::TraitItem {
@@ -1139,7 +1089,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>>
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
let abi = tcx.hir().get_foreign_abi(hir_id);
- compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi)
+ compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
}
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
@@ -1215,7 +1165,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
fn_sig,
Applicability::MachineApplicable,
);
- } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
+ } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) {
diag.span_suggestion(
ty.span,
"replace with an appropriate return type",
@@ -1247,12 +1197,10 @@ fn infer_return_ty_for_fn_sig<'tcx>(
}
}
-// FIXME(vincenzopalazzo): remove the hir item when the refactoring is stable
fn suggest_impl_trait<'tcx>(
tcx: TyCtxt<'tcx>,
ret_ty: Ty<'tcx>,
span: Span,
- _hir_id: hir::HirId,
def_id: LocalDefId,
) -> Option<String> {
let format_as_assoc: fn(_, _, _, _, _) -> _ =
@@ -1338,9 +1286,12 @@ fn suggest_impl_trait<'tcx>(
None
}
-fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
+fn impl_trait_ref(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
let icx = ItemCtxt::new(tcx, def_id);
- let impl_ = tcx.hir().expect_item(def_id.expect_local()).expect_impl();
+ let impl_ = tcx.hir().expect_item(def_id).expect_impl();
impl_
.of_trait
.as_ref()
@@ -1380,9 +1331,9 @@ fn check_impl_constness(
}
}
-fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
+fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
- let item = tcx.hir().expect_item(def_id.expect_local());
+ let item = tcx.hir().expect_item(def_id);
match &item.kind {
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Negative(span),
@@ -1465,16 +1416,16 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
fn compute_sig_of_foreign_fn_decl<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ def_id: LocalDefId,
decl: &'tcx hir::FnDecl<'tcx>,
abi: abi::Abi,
) -> ty::PolyFnSig<'tcx> {
let unsafety = if abi == abi::Abi::RustIntrinsic {
- intrinsic_operation_unsafety(tcx, def_id)
+ intrinsic_operation_unsafety(tcx, def_id.to_def_id())
} else {
hir::Unsafety::Unsafe
};
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let fty =
ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
@@ -1491,17 +1442,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
.source_map()
.span_to_snippet(ast_ty.span)
.map_or_else(|_| String::new(), |s| format!(" `{}`", s));
- tcx.sess
- .struct_span_err(
- ast_ty.span,
- &format!(
- "use of SIMD type{} in FFI is highly experimental and \
- may result in invalid code",
- snip
- ),
- )
- .help("add `#![feature(simd_ffi)]` to the crate attributes to enable")
- .emit();
+ tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
}
};
for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
@@ -1515,31 +1456,28 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
fty
}
-fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- match tcx.hir().get_if_local(def_id) {
- Some(Node::ForeignItem(..)) => true,
- Some(_) => false,
- _ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id),
+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: DefId) -> Option<hir::GeneratorKind> {
- match tcx.hir().get_if_local(def_id) {
- Some(Node::Expr(&rustc_hir::Expr {
+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 {
kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }),
..
- })) => tcx.hir().body(body).generator_kind(),
- Some(_) => None,
- _ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
+ }) => tcx.hir().body(body).generator_kind(),
+ _ => None,
}
}
-fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
- match tcx.hir().get_if_local(def_id) {
- Some(Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. })) => {
+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)
}
- Some(_) => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
- _ => bug!("tried getting opaque_ty_origin for non-local def-id {:?}", def_id),
+ _ => 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 127d4fa90..119933697 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -5,16 +5,16 @@ use hir::{
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
-pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
+pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*;
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let node = tcx.hir().get(hir_id);
let parent_def_id = match node {
@@ -121,7 +121,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
Some(parent_def_id.to_def_id())
}
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
- Some(tcx.typeck_root_def_id(def_id))
+ Some(tcx.typeck_root_def_id(def_id.to_def_id()))
}
// Exclude `GlobalAsm` here which cannot have generics.
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@@ -140,7 +140,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
}
}
Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
- Some(tcx.typeck_root_def_id(def_id))
+ Some(tcx.typeck_root_def_id(def_id.to_def_id()))
}
Node::Item(item) => match item.kind {
ItemKind::OpaqueTy(hir::OpaqueTy {
@@ -189,7 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
let opt_self = Some(ty::GenericParamDef {
index: 0,
name: kw::SelfUpper,
- def_id,
+ def_id: def_id.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
@@ -326,7 +326,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {
index: next_index(),
name: Symbol::intern(arg),
- def_id,
+ def_id: def_id.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
}));
@@ -339,7 +339,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
params.push(ty::GenericParamDef {
index: next_index(),
name: Symbol::intern("<const_ty>"),
- def_id,
+ def_id: def_id.to_def_id(),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
});
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 9cf3ff65a..2e56d2463 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,8 +3,8 @@ use crate::astconv::AstConv;
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
-use rustc_span::def_id::DefId;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
/// For associated types we include both bounds written on the type
@@ -16,12 +16,12 @@ use rustc_span::Span;
/// `hr-associated-type-bound-1.rs`.
fn associated_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
- assoc_item_def_id: DefId,
+ assoc_item_def_id: LocalDefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
let item_ty = tcx.mk_projection(
- assoc_item_def_id,
+ assoc_item_def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
);
@@ -30,8 +30,8 @@ fn associated_type_bounds<'tcx>(
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
- let trait_def_id = tcx.parent(assoc_item_def_id);
- let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
+ let trait_def_id = tcx.local_parent(assoc_item_def_id);
+ let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
match pred.kind().skip_binder() {
@@ -45,7 +45,11 @@ fn associated_type_bounds<'tcx>(
});
let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent));
- debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
+ debug!(
+ "associated_type_bounds({}) = {:?}",
+ tcx.def_path_str(assoc_item_def_id.to_def_id()),
+ all_bounds
+ );
all_bounds
}
@@ -56,19 +60,12 @@ fn associated_type_bounds<'tcx>(
#[instrument(level = "trace", skip(tcx), ret)]
fn opaque_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
- opaque_def_id: DefId,
+ opaque_def_id: LocalDefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
+ item_ty: Ty<'tcx>,
span: Span,
- in_trait: bool,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
ty::print::with_no_queries!({
- let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id);
- let item_ty = if in_trait {
- tcx.mk_projection(opaque_def_id, substs)
- } else {
- tcx.mk_opaque(opaque_def_id, substs)
- };
-
let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
// Opaque types are implicitly sized unless a `?Sized` bound is found
@@ -81,9 +78,31 @@ fn opaque_type_bounds<'tcx>(
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
- def_id: DefId,
+ def_id: LocalDefId,
) -> &'_ [(ty::Predicate<'_>, Span)] {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ 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(
+ tcx,
+ opaque_def_id.expect_local(),
+ opaque_ty.bounds,
+ tcx.mk_projection(
+ def_id.to_def_id(),
+ ty::InternalSubsts::identity_for_item(tcx, def_id),
+ ),
+ item.span,
+ );
+ }
+ // These should have been fed!
+ Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
+ None => {}
+ }
+
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _),
@@ -94,7 +113,15 @@ pub(super) fn explicit_item_bounds(
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
span,
..
- }) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait),
+ }) => {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+ tcx.mk_projection(def_id.to_def_id(), substs)
+ } else {
+ tcx.mk_opaque(def_id.to_def_id(), substs)
+ };
+ opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
+ }
_ => bug!("item_bounds called on {:?}", def_id),
}
}
@@ -103,12 +130,9 @@ 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_predicates(
- tcx,
- tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
- )
- .map(|obligation| obligation.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)
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 2badd66e3..9358ed612 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -62,15 +62,16 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
/// N.B., this does not include any implied/inferred constraints.
#[instrument(level = "trace", skip(tcx), ret)]
-fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let node = tcx.hir().get(hir_id);
let mut is_trait = None;
let mut is_default_impl_trait = None;
+ // FIXME: Should ItemCtxt take a LocalDefId?
let icx = ItemCtxt::new(tcx, def_id);
const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
@@ -99,7 +100,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
| ItemKind::Union(_, generics) => generics,
ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id));
+ is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id()));
generics
}
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
@@ -124,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// 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.super_predicates_of(def_id).predicates.iter().cloned());
+ predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
}
// In default impls, we can assume that the self type implements
@@ -253,7 +254,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
if tcx.features().generic_const_exprs {
- predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
+ predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
}
let mut predicates: Vec<_> = predicates.into_iter().collect();
@@ -392,18 +393,18 @@ pub(super) fn trait_explicit_predicates_and_bounds(
def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
- gather_explicit_predicates_of(tcx, def_id.to_def_id())
+ gather_explicit_predicates_of(tcx, def_id)
}
pub(super) fn explicit_predicates_of<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ def_id: LocalDefId,
) -> ty::GenericPredicates<'tcx> {
let def_kind = tcx.def_kind(def_id);
if let DefKind::Trait = def_kind {
// Remove bounds on associated types from the predicates, they will be
// returned by `explicit_item_bounds`.
- let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
+ let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let is_assoc_item_ty = |ty: Ty<'tcx>| {
@@ -418,7 +419,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
// supertrait).
if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.substs == trait_identity_substs
- && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
+ && tcx.associated_item(projection.def_id).container_id(tcx)
+ == def_id.to_def_id()
} else {
false
}
@@ -449,7 +451,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
} else {
if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = tcx.hir().get_parent_item(hir_id);
if let Some(defaulted_param_def_id) =
@@ -532,89 +534,136 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
}
+#[derive(Copy, Clone, Debug)]
+pub enum PredicateFilter {
+ /// All predicates may be implied by the trait
+ All,
+
+ /// Only traits that reference `Self: ..` are implied by the trait
+ SelfOnly,
+
+ /// Only traits that reference `Self: ..` and define an associated type
+ /// with the given ident are implied by the trait
+ SelfThatDefines(Ident),
+}
+
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
pub(super) fn super_predicates_of(
tcx: TyCtxt<'_>,
- trait_def_id: DefId,
+ trait_def_id: LocalDefId,
+) -> ty::GenericPredicates<'_> {
+ implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
+}
+
+pub(super) fn super_predicates_that_define_assoc_type(
+ tcx: TyCtxt<'_>,
+ (trait_def_id, assoc_name): (DefId, Ident),
+) -> ty::GenericPredicates<'_> {
+ implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
+}
+
+pub(super) fn implied_predicates_of(
+ tcx: TyCtxt<'_>,
+ trait_def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
- tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
+ if tcx.is_trait_alias(trait_def_id.to_def_id()) {
+ implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
+ } else {
+ tcx.super_predicates_of(trait_def_id)
+ }
}
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
-pub(super) fn super_predicates_that_define_assoc_type(
+pub(super) fn implied_predicates_with_filter(
tcx: TyCtxt<'_>,
- (trait_def_id, assoc_name): (DefId, Option<Ident>),
+ trait_def_id: DefId,
+ filter: PredicateFilter,
) -> ty::GenericPredicates<'_> {
- if trait_def_id.is_local() {
- debug!("local trait");
- let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
-
- let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
- bug!("trait_node_id {} is not an item", trait_hir_id);
- };
+ let Some(trait_def_id) = trait_def_id.as_local() else {
+ // if `assoc_name` is None, then the query should've been redirected to an
+ // external provider
+ assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
+ return tcx.super_predicates_of(trait_def_id);
+ };
- let (generics, bounds) = match item.kind {
- hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
- hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
- _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
- };
+ let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id);
- let icx = ItemCtxt::new(tcx, trait_def_id);
+ let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
+ bug!("trait_node_id {} is not an item", trait_hir_id);
+ };
- // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
- let self_param_ty = tcx.types.self_param;
- let superbounds1 = if let Some(assoc_name) = assoc_name {
- icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
- } else {
- icx.astconv().compute_bounds(self_param_ty, bounds)
- };
+ let (generics, bounds) = match item.kind {
+ hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
+ hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
+ _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
+ };
- let superbounds1 = superbounds1.predicates();
-
- // Convert any explicit superbounds in the where-clause,
- // e.g., `trait Foo where Self: Bar`.
- // In the case of trait aliases, however, we include all bounds in the where-clause,
- // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
- // as one of its "superpredicates".
- let is_trait_alias = tcx.is_trait_alias(trait_def_id);
- let superbounds2 = icx.type_parameter_bounds_in_generics(
- generics,
- item.owner_id.def_id,
- self_param_ty,
- OnlySelfBounds(!is_trait_alias),
- assoc_name,
- );
+ let icx = ItemCtxt::new(tcx, trait_def_id);
+
+ let self_param_ty = tcx.types.self_param;
+ 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),
+ // Also include all where clause bounds
+ icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ OnlySelfBounds(false),
+ None,
+ ),
+ ),
+ PredicateFilter::SelfOnly => (
+ // Convert the bounds that follow the colon (or equal in trait aliases)
+ icx.astconv().compute_bounds(self_param_ty, bounds),
+ // Include where clause bounds for `Self`
+ icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ OnlySelfBounds(true),
+ None,
+ ),
+ ),
+ 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),
+ // Include where clause bounds for `Self` that reference the associated name
+ icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ OnlySelfBounds(true),
+ Some(assoc_name),
+ ),
+ ),
+ };
- // Combine the two lists to form the complete set of superbounds:
- let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
- debug!(?superbounds);
+ // 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));
+ debug!(?implied_bounds);
+ // Now require that immediate supertraits are converted,
+ // which will, in turn, reach indirect supertraits.
+ if matches!(filter, PredicateFilter::SelfOnly) {
// Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits.
- if assoc_name.is_none() {
- // Now require that immediate supertraits are converted,
- // which will, in turn, reach indirect supertraits.
- for &(pred, span) in superbounds {
- debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) =
- pred.kind().skip_binder()
- {
- tcx.at(span).super_predicates_of(bound.def_id());
- }
+ for &(pred, span) in implied_bounds {
+ debug!("superbound: {:?}", pred);
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
+ tcx.at(span).super_predicates_of(bound.def_id());
}
}
-
- ty::GenericPredicates { parent: None, predicates: superbounds }
- } else {
- // if `assoc_name` is None, then the query should've been redirected to an
- // external provider
- assert!(assoc_name.is_some());
- tcx.super_predicates_of(trait_def_id)
}
+
+ ty::GenericPredicates { parent: None, predicates: implied_bounds }
}
/// Returns the predicates defined on `item_def_id` of the form
@@ -622,7 +671,7 @@ pub(super) fn super_predicates_that_define_assoc_type(
#[instrument(level = "trace", skip(tcx))]
pub(super) fn type_param_predicates(
tcx: TyCtxt<'_>,
- (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
+ (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident),
) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
@@ -637,21 +686,21 @@ pub(super) fn type_param_predicates(
let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id));
// Don't look for bounds where the type parameter isn't in scope.
- let parent = if item_def_id == param_owner.to_def_id() {
+ let parent = if item_def_id == param_owner {
None
} else {
- tcx.generics_of(item_def_id).parent
+ tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
};
let mut result = parent
.map(|parent| {
let icx = ItemCtxt::new(tcx, parent);
- icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
+ icx.get_type_parameter_bounds(DUMMY_SP, def_id, assoc_name)
})
.unwrap_or_default();
let mut extend = None;
- let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
+ let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id);
let ast_generics = match tcx.hir().get(item_hir_id) {
Node::TraitItem(item) => &item.generics,
@@ -673,7 +722,8 @@ pub(super) fn type_param_predicates(
ItemKind::Trait(_, _, generics, ..) => {
// Implied `Self: Trait` and supertrait bounds.
if param_id == item_hir_id {
- let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
+ let identity_trait_ref =
+ ty::TraitRef::identity(tcx, item_def_id.to_def_id());
extend =
Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
}
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 65a9052a6..e758fe95d 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -17,7 +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::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
@@ -1051,9 +1051,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
}
-fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
+fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
- let param_def_id = param_def_id.expect_local();
let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else {
bug!("expected GenericParam for object_lifetime_default");
};
@@ -1427,25 +1426,25 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
let use_span = self.tcx.hir().span(hir_id);
let def_span = self.tcx.def_span(param_def_id);
- match self.tcx.def_kind(param_def_id) {
+ let guar = match self.tcx.def_kind(param_def_id) {
DefKind::ConstParam => {
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
use_span,
def_span,
- });
+ })
}
DefKind::TyParam => {
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
use_span,
def_span,
- });
+ })
}
_ => unreachable!(),
- }
- return;
+ };
+ self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+ } else {
+ self.map.defs.insert(hir_id, def);
}
-
- self.map.defs.insert(hir_id, def);
return;
}
@@ -1462,7 +1461,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
depth: usize,
generic_args: &'tcx hir::GenericArgs<'tcx>,
) {
- if generic_args.parenthesized {
+ if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
self.visit_fn_like_elision(
generic_args.inputs(),
Some(generic_args.bindings[0].ty()),
@@ -1641,7 +1640,59 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
},
s: self.scope,
};
- if let Some(type_def_id) = type_def_id {
+ // If the binding is parenthesized, then this must be `feature(return_type_notation)`.
+ // In that case, introduce a binder over all of the function's early and late bound vars.
+ //
+ // For example, given
+ // ```
+ // trait Foo {
+ // async fn x<'r, T>();
+ // }
+ // ```
+ // and a bound that looks like:
+ // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
+ // this is going to expand to something like:
+ // `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
+ 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)
+ {
+ 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),
+ ),
+ ty::GenericParamDefKind::Type { .. } => ty::BoundVariableKind::Ty(
+ 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()
+ } else {
+ self.tcx.sess.delay_span_bug(
+ binding.ident.span,
+ "bad return type notation here",
+ );
+ vec![]
+ };
+ self.with(scope, |this| {
+ let scope = Scope::Supertrait { bound_vars, s: this.scope };
+ this.with(scope, |this| {
+ let (bound_vars, _) = this.poly_trait_ref_binder_info();
+ this.record_late_bound_vars(binding.hir_id, bound_vars);
+ this.visit_assoc_type_binding(binding)
+ });
+ });
+ } else if let Some(type_def_id) = type_def_id {
let bound_vars =
BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
self.with(scope, |this| {
@@ -1698,8 +1749,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
if trait_defines_associated_type_named(def_id) {
break Some(bound_vars.into_iter().collect());
}
- let predicates =
- tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
+ let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 50073d94e..c173bd913 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -8,9 +8,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{
- self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
-};
+use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
@@ -62,7 +60,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
.find(|(_, node)| matches!(node, OwnerNode::Item(_)))
.unwrap()
.0
- .to_def_id();
+ .def_id;
let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>;
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
@@ -243,24 +241,46 @@ fn get_path_containing_arg_in_pat<'hir>(
arg_path
}
-pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> {
- let def_id = def_id.expect_local();
+pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty<'_>> {
+ // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl
+ // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
+ // associated type in the impl.
+ if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) =
+ tcx.opt_rpitit_info(def_id.to_def_id())
+ {
+ 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()]);
+ }
+ Err(_) => {
+ return ty::EarlyBinder(tcx.ty_error_with_message(
+ DUMMY_SP,
+ "Could not collect return position impl trait in trait tys",
+ ));
+ }
+ }
+ }
+
use rustc_hir::*;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let icx = ItemCtxt::new(tcx, def_id.to_def_id());
+ let icx = ItemCtxt::new(tcx, def_id);
let output = match tcx.hir().get(hir_id) {
Node::TraitItem(item) => match item.kind {
TraitItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id.to_def_id(), substs)
}
TraitItemKind::Const(ty, body_id) => body_id
.and_then(|body_id| {
- is_suggestable_infer_ty(ty)
- .then(|| infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant",))
+ is_suggestable_infer_ty(ty).then(|| {
+ infer_placeholder_type(
+ tcx, def_id, body_id, ty.span, item.ident, "constant",
+ )
+ })
})
.unwrap_or_else(|| icx.to_ty(ty)),
TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
@@ -271,7 +291,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
Node::ImplItem(item) => match item.kind {
ImplItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id.to_def_id(), substs)
}
ImplItemKind::Const(ty, body_id) => {
@@ -316,22 +336,23 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
}
}
ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty),
- ItemKind::Impl(hir::Impl { self_ty, .. }) => {
- match self_ty.find_self_aliases() {
- spans if spans.len() > 0 => {
- let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () });
- tcx.ty_error(guar)
- },
- _ => icx.to_ty(*self_ty),
+ ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() {
+ spans if spans.len() > 0 => {
+ let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf {
+ span: spans.into(),
+ note: (),
+ });
+ tcx.ty_error(guar)
}
+ _ => icx.to_ty(*self_ty),
},
ItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id.to_def_id(), substs)
}
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
let def = tcx.adt_def(def_id);
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_adt(def, substs)
}
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
@@ -344,8 +365,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
in_trait,
..
}) => {
- if in_trait {
- assert!(tcx.impl_defaultness(owner).has_value());
+ if in_trait && !tcx.impl_defaultness(owner).has_value() {
+ span_bug!(
+ tcx.def_span(def_id),
+ "tried to get type of this RPITIT with no definition"
+ );
}
find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
}
@@ -368,7 +392,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
Node::ForeignItem(foreign_item) => match foreign_item.kind {
ForeignItemKind::Fn(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id.to_def_id(), substs)
}
ForeignItemKind::Static(t, _) => icx.to_ty(t),
@@ -380,7 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity()
}
VariantData::Tuple(..) => {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id.to_def_id(), substs)
}
},
@@ -413,7 +437,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. })
if anon_const.hir_id == hir_id =>
{
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
substs.as_inline_const().ty()
}
@@ -434,15 +458,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
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)
+ 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 {
@@ -456,7 +477,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
def_id.to_def_id(),
);
if let Some(assoc_item) = assoc_item {
- tcx.type_of(assoc_item.def_id).subst_identity()
+ 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(
@@ -466,10 +489,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
}
}
- Node::TypeBinding(
- TypeBinding { hir_id: binding_id, gen_args, kind, ident, .. },
- ) if let Node::TraitRef(trait_ref) =
- tcx.hir().get_parent(*binding_id)
+ 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 {
@@ -498,15 +524,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
},
def_id.to_def_id(),
);
- if let Some(param)
- = assoc_item.map(|item| &tcx.generics_of(item.def_id).params[idx]).filter(|param| param.kind.is_ty_or_const())
+ 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).subst_identity()
+ 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 associated const on trait",
+ "Could not find const param on associated item",
)
}
}
@@ -574,7 +603,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
found: Option<ty::OpaqueHiddenType<'tcx>>,
/// In the presence of dead code, typeck may figure out a hidden type
- /// while borrowck will now. We collect these cases here and check at
+ /// 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>>,
}
@@ -746,7 +775,7 @@ fn find_opaque_ty_constraints_for_rpit(
// 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 {
+ for (&def_id, &concrete_type) in concrete_opaque_types {
if def_id != self.def_id {
// Ignore constraints for other opaque types.
continue;
@@ -842,28 +871,6 @@ fn infer_placeholder_type<'a>(
item_ident: Ident,
kind: &'static str,
) -> Ty<'a> {
- // Attempts to make the type nameable by turning FnDefs into FnPtrs.
- struct MakeNameable<'tcx> {
- tcx: TyCtxt<'tcx>,
- }
-
- impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MakeNameable<'tcx> {
- fn interner(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- let ty = match *ty.kind() {
- ty::FnDef(def_id, substs) => {
- self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
- }
- _ => ty,
- };
-
- ty.super_fold_with(self)
- }
- }
-
let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
// If this came from a free `const` or `static mut?` item,
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 3e0692757..2a3a68348 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_errors::{
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
MultiSpan,
};
-use rustc_macros::Diagnostic;
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::{symbol::Ident, Span, Symbol};
@@ -129,6 +129,18 @@ pub struct AssocTypeBindingNotAllowed {
#[primary_span]
#[label]
pub span: Span,
+
+ #[subdiagnostic]
+ pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(hir_analysis_parenthesized_fn_trait_expansion)]
+pub struct ParenthesizedFnTraitExpansion {
+ #[primary_span]
+ pub span: Span,
+
+ pub expanded_type: String,
}
#[derive(Diagnostic)]
@@ -316,6 +328,14 @@ pub(crate) struct TrackCallerOnMain {
}
#[derive(Diagnostic)]
+#[diag(hir_analysis_target_feature_on_main)]
+pub(crate) struct TargetFeatureOnMain {
+ #[primary_span]
+ #[label(hir_analysis_target_feature_on_main)]
+ pub main: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(hir_analysis_start_not_track_caller)]
pub(crate) struct StartTrackCaller {
#[primary_span]
@@ -325,6 +345,15 @@ pub(crate) struct StartTrackCaller {
}
#[derive(Diagnostic)]
+#[diag(hir_analysis_start_not_target_feature)]
+pub(crate) struct StartTargetFeature {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub start: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(hir_analysis_start_not_async, code = "E0752")]
pub(crate) struct StartAsync {
#[primary_span]
@@ -399,3 +428,206 @@ pub(crate) enum CannotCaptureLateBoundInAnonConst {
def_span: Span,
},
}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_variances_of)]
+pub(crate) struct VariancesOf {
+ #[primary_span]
+ pub span: Span,
+ pub variances_of: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_pass_to_variadic_function, code = "E0617")]
+pub(crate) struct PassToVariadicFunction<'tcx, 'a> {
+ #[primary_span]
+ pub span: Span,
+ pub ty: Ty<'tcx>,
+ pub cast_ty: &'a str,
+ #[suggestion(code = "{replace}", applicability = "machine-applicable")]
+ pub sugg_span: Option<Span>,
+ pub replace: String,
+ #[help]
+ pub help: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = "E0607")]
+pub(crate) struct CastThinPointerToFatPointer<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ pub expr_ty: Ty<'tcx>,
+ pub cast_ty: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_invalid_union_field, code = "E0740")]
+pub(crate) struct InvalidUnionField {
+ #[primary_span]
+ pub field_span: Span,
+ #[subdiagnostic]
+ pub sugg: InvalidUnionFieldSuggestion,
+ #[note]
+ pub note: (),
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_on_non_rpitit)]
+pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ pub ty: Ty<'tcx>,
+ #[label]
+ pub fn_span: Option<Span>,
+ #[note]
+ pub note: (),
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")]
+pub(crate) struct InvalidUnionFieldSuggestion {
+ #[suggestion_part(code = "std::mem::ManuallyDrop<")]
+ pub lo: Span,
+ #[suggestion_part(code = ">")]
+ pub hi: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_equality_bound)]
+pub(crate) struct ReturnTypeNotationEqualityBound {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_missing_method)]
+pub(crate) struct ReturnTypeNotationMissingMethod {
+ #[primary_span]
+ pub span: Span,
+ pub trait_name: Symbol,
+ pub assoc_name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
+pub(crate) struct PlaceholderNotAllowedItemSignatures {
+ #[primary_span]
+ #[label]
+ pub spans: Vec<Span>,
+ pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")]
+pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")]
+ pub inferred_sugg: Option<Span>,
+ pub bound: String,
+ #[subdiagnostic]
+ pub mpart_sugg: Option<AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+ hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion,
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+ #[suggestion_part(code = "{first}")]
+ pub fspan: Span,
+ pub first: String,
+ #[suggestion_part(code = "{second}")]
+ pub sspan: Span,
+ pub second: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")]
+#[note]
+pub(crate) struct EnumDiscriminantOverflowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub discr: String,
+ pub item_name: Symbol,
+ pub wrapped_discr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_paren_sugar_attribute)]
+#[help]
+pub(crate) struct ParenSugarAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_implement_one_of_attribute)]
+pub(crate) struct MustImplementOneOfAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_be_name_of_associated_function)]
+pub(crate) struct MustBeNameOfAssociatedFunction {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_function_not_have_default_implementation)]
+pub(crate) struct FunctionNotHaveDefaultImplementation {
+ #[primary_span]
+ pub span: Span,
+ #[note]
+ pub note_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_implement_not_function)]
+pub(crate) struct MustImplementNotFunction {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub span_note: MustImplementNotFunctionSpanNote,
+ #[subdiagnostic]
+ pub note: MustImplementNotFunctionNote,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_analysis_must_implement_not_function_span_note)]
+pub(crate) struct MustImplementNotFunctionSpanNote {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_analysis_must_implement_not_function_note)]
+pub(crate) struct MustImplementNotFunctionNote {}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_function_not_found_in_trait)]
+pub(crate) struct FunctionNotFoundInTrait {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_functions_names_duplicated)]
+#[note]
+pub(crate) struct FunctionNamesDuplicated {
+ #[primary_span]
+ pub spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_simd_ffi_highly_experimental)]
+#[help]
+pub(crate) struct SIMDFFIHighlyExperimental {
+ #[primary_span]
+ pub span: Span,
+ pub snip: String,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index e330fcc78..8269a6dde 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -7,7 +7,7 @@ use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::def_id::LocalDefId;
-use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::{self, ObligationCtxt};
pub fn provide(providers: &mut Providers) {
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
@@ -31,7 +31,7 @@ fn diagnostic_hir_wf_check<'tcx>(
tcx.sess
.delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
- let icx = ItemCtxt::new(tcx, def_id.to_def_id());
+ let icx = ItemCtxt::new(tcx, def_id);
// To perform HIR-based WF checking, we iterate over all HIR types
// that occur 'inside' the item we're checking. For example,
@@ -66,35 +66,35 @@ fn diagnostic_hir_wf_check<'tcx>(
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
let infcx = self.tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(&infcx);
+
let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
let cause = traits::ObligationCause::new(
ty.span,
self.def_id,
traits::ObligationCauseCode::WellFormed(None),
);
- let errors = traits::fully_solve_obligation(
- &infcx,
- traits::Obligation::new(
- self.tcx,
- cause,
- self.param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())),
- ),
- );
- if !errors.is_empty() {
- debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
- for error in errors {
- if error.obligation.predicate == self.predicate {
- // Save the cause from the greatest depth - this corresponds
- // to picking more-specific types (e.g. `MyStruct<u8>`)
- // over less-specific types (e.g. `Option<MyStruct<u8>>`)
- if self.depth >= self.cause_depth {
- self.cause = Some(error.obligation.cause);
- self.cause_depth = self.depth
- }
+
+ ocx.register_obligation(traits::Obligation::new(
+ self.tcx,
+ cause,
+ self.param_env,
+ ty::PredicateKind::WellFormed(tcx_ty.into()),
+ ));
+
+ for error in ocx.select_all_or_error() {
+ debug!("Wf-check got error for {:?}: {:?}", ty, error);
+ if error.obligation.predicate == self.predicate {
+ // Save the cause from the greatest depth - this corresponds
+ // to picking more-specific types (e.g. `MyStruct<u8>`)
+ // over less-specific types (e.g. `Option<MyStruct<u8>>`)
+ if self.depth >= self.cause_depth {
+ self.cause = Some(error.obligation.cause);
+ self.cause_depth = self.depth
}
}
}
+
self.depth += 1;
intravisit::walk_ty(self, ty);
self.depth -= 1;
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 daa5d1570..eb2fc3952 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
@@ -168,20 +168,19 @@ fn get_impl_substs(
let assumed_wf_types =
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.to_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 errors = ocx.select_all_or_error();
if !errors.is_empty() {
- ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
return None;
}
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
- let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
- let _ =
- infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+ let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
let span = tcx.def_span(impl1_def_id);
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
@@ -318,30 +317,20 @@ fn check_predicates<'tcx>(
span: Span,
) {
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
- let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
- tcx,
- std::iter::zip(
- instantiated.predicates,
- // Don't drop predicates (unsound!) because `spans` is too short
- instantiated.spans.into_iter().chain(std::iter::repeat(span)),
- ),
- )
- .map(|obligation| (obligation.predicate, obligation.cause.span))
- .collect();
+ let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect();
let mut impl2_predicates = if impl2_node.is_from_trait() {
// Always applicable traits have to be always applicable without any
// assumptions.
Vec::new()
} else {
- traits::elaborate_predicates(
+ traits::elaborate(
tcx,
tcx.predicates_of(impl2_node.def_id())
.instantiate(tcx, impl2_substs)
.predicates
.into_iter(),
)
- .map(|obligation| obligation.predicate)
.collect()
};
debug!(?impl1_predicates, ?impl2_predicates);
@@ -361,12 +350,16 @@ fn check_predicates<'tcx>(
// which is sound because we forbid impls like the following
//
// impl<D: Debug> AlwaysApplicable for D { }
- let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| {
- matches!(
- trait_predicate_kind(tcx, predicate),
- Some(TraitSpecializationKind::AlwaysApplicable)
- )
- });
+ let always_applicable_traits = impl1_predicates
+ .iter()
+ .copied()
+ .filter(|&(predicate, _)| {
+ matches!(
+ trait_predicate_kind(tcx, predicate),
+ Some(TraitSpecializationKind::AlwaysApplicable)
+ )
+ })
+ .map(|(pred, _span)| pred);
// Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
@@ -376,14 +369,10 @@ fn check_predicates<'tcx>(
.unwrap();
assert!(!obligations.needs_infer());
- impl2_predicates.extend(
- traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate),
- )
+ impl2_predicates
+ .extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
}
- impl2_predicates.extend(
- traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
- .map(|obligation| obligation.predicate),
- );
+ impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
for (predicate, span) in impl1_predicates {
if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {
@@ -528,7 +517,7 @@ fn trait_predicate_kind<'tcx>(
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
| ty::PredicateKind::Clause(ty::Clause::Projection(_))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | ty::PredicateKind::AliasEq(..)
+ | ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 33c132fd5..27e561803 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -67,10 +67,9 @@ This API is completely unstable and subject to change.
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
#![feature(slice_partition_dedup)]
#![feature(try_blocks)]
-#![feature(is_some_and)]
#![feature(type_alias_impl_trait)]
#![recursion_limit = "256"]
@@ -102,7 +101,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
use rustc_hir::Node;
-use rustc_infer::infer::{InferOk, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_macros::fluent_messages;
use rustc_middle::middle;
use rustc_middle::ty::query::Providers;
@@ -113,14 +112,14 @@ use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
use std::ops::Not;
use astconv::AstConv;
use bounds::Bounds;
-fluent_messages! { "../locales/en-US.ftl" }
+fluent_messages! { "../messages.ftl" }
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
@@ -160,24 +159,21 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
fn require_same_types<'tcx>(
tcx: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
-) -> bool {
+) {
let infcx = &tcx.infer_ctxt().build();
- let param_env = ty::ParamEnv::empty();
- let errors = match infcx.at(cause, param_env).eq(expected, actual) {
- Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
+ let ocx = ObligationCtxt::new(infcx);
+ match ocx.eq(cause, param_env, expected, actual) {
+ Ok(()) => {
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
+ }
+ }
Err(err) => {
infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
- return false;
- }
- };
-
- match &errors[..] {
- [] => true,
- errors => {
- infcx.err_ctxt().report_fulfillment_errors(errors, None);
- false
}
}
}
@@ -283,10 +279,21 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
error = true;
}
+ if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
+ // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
+ && !tcx.sess.target.is_like_wasm
+ && !tcx.sess.opts.actually_rustdoc
+ {
+ tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
+ error = true;
+ }
+
if error {
return;
}
+ // Main should have no WC, so empty param env is OK here.
+ let param_env = ty::ParamEnv::empty();
let expected_return_type;
if let Some(term_did) = tcx.lang_items().termination() {
let return_ty = main_fnsig.output();
@@ -297,8 +304,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
}
let return_ty = return_ty.skip_binder();
let infcx = tcx.infer_ctxt().build();
- // Main should have no WC, so empty param env is OK here.
- let param_env = ty::ParamEnv::empty();
let cause = traits::ObligationCause::new(
return_ty_span,
main_diagnostics_def_id,
@@ -309,7 +314,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
error = true;
}
// now we can take the return type of the given main function
@@ -334,6 +339,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
main_diagnostics_def_id,
ObligationCauseCode::MainFunctionType,
),
+ param_env,
se_ty,
tcx.mk_fn_ptr(main_fnsig),
);
@@ -373,6 +379,18 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
});
error = true;
}
+ if attr.has_name(sym::target_feature)
+ // Calling functions with `#[target_feature]` is
+ // not unsafe on WASM, see #84988
+ && !tcx.sess.target.is_like_wasm
+ && !tcx.sess.opts.actually_rustdoc
+ {
+ tcx.sess.emit_err(errors::StartTargetFeature {
+ span: attr.span,
+ start: start_span,
+ });
+ error = true;
+ }
}
if error {
@@ -396,6 +414,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
start_def_id,
ObligationCauseCode::StartFunctionType,
),
+ ty::ParamEnv::empty(), // start should not have any where bounds.
se_ty,
tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()),
);
@@ -492,7 +511,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
// def-ID that will be used to determine the traits/predicates in
// scope. This is derived from the enclosing item-like thing.
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
- let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
+ let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
item_cx.astconv().ast_ty_to_ty(hir_ty)
}
@@ -505,7 +524,7 @@ pub fn hir_trait_to_predicates<'tcx>(
// def-ID that will be used to determine the traits/predicates in
// scope. This is derived from the enclosing item-like thing.
let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id);
- let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
+ let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id);
let mut bounds = Bounds::default();
let _ = &item_cx.astconv().instantiate_poly_trait_ref(
hir_trait,
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 9ee678597..357deb07b 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -56,7 +56,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::WellFormed(..)
- | ty::PredicateKind::AliasEq(..)
+ | ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index a8b33c74b..d53c429ca 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -1,7 +1,7 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::Span;
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 81fe32000..da72d2584 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -1,6 +1,6 @@
use hir::Node;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
@@ -17,8 +17,8 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
}
-fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Clause<'_>, Span)] {
- let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
+fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
+ let id = tcx.hir().local_def_id_to_hir_id(item_def_id);
if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization()
{
@@ -45,7 +45,8 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Clause<'_
hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => {
let crate_map = tcx.inferred_outlives_crate(());
- let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]);
+ let predicates =
+ crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
let mut pred: Vec<String> = predicates
diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs
index fa2ac5659..60f8e246a 100644
--- a/compiler/rustc_hir_analysis/src/outlives/test.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/test.rs
@@ -6,7 +6,7 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
for id in tcx.hir().items() {
// For unit testing: check for a special "rustc_outlives"
// attribute and report an error with various results if found.
- if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_outlives) {
+ if tcx.has_attr(id.owner_id, sym::rustc_outlives) {
let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id);
struct_span_err!(
tcx.sess,
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 089491bef..0bfbf99cb 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
@@ -1,5 +1,5 @@
-use crate::structured_errors::StructuredDiagnostic;
-use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
+use crate::{errors, structured_errors::StructuredDiagnostic};
+use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
use rustc_middle::ty::{Ty, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::Span;
@@ -21,27 +21,26 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
}
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let mut err = self.sess.struct_span_err_with_code(
- self.span,
- &format!("can't pass `{}` to variadic function", self.ty),
- self.code(),
- );
+ let (sugg_span, replace, help) =
+ if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
+ (Some(self.span), format!("{} as {}", snippet, self.cast_ty), None)
+ } else {
+ (None, "".to_string(), Some(()))
+ };
+
+ let mut err = self.sess.create_err(errors::PassToVariadicFunction {
+ span: self.span,
+ ty: self.ty,
+ cast_ty: self.cast_ty,
+ help,
+ replace,
+ sugg_span,
+ });
if self.ty.references_error() {
err.downgrade_to_delayed_bug();
}
- if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.span) {
- err.span_suggestion(
- self.span,
- &format!("cast the value to `{}`", self.cast_ty),
- format!("{} as {}", snippet, self.cast_ty),
- Applicability::MachineApplicable,
- );
- } else {
- err.help(&format!("cast the value to `{}`", self.cast_ty));
- }
-
err
}
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index 3b9fb3678..910417abe 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
@@ -1,4 +1,4 @@
-use crate::structured_errors::StructuredDiagnostic;
+use crate::{errors, structured_errors::StructuredDiagnostic};
use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
use rustc_middle::ty::{Ty, TypeVisitableExt};
use rustc_session::Session;
@@ -21,14 +21,11 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
}
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let mut err = self.sess.struct_span_err_with_code(
- self.span,
- &format!(
- "cannot cast thin pointer `{}` to fat pointer `{}`",
- self.expr_ty, self.cast_ty
- ),
- self.code(),
- );
+ let mut err = self.sess.create_err(errors::CastThinPointerToFatPointer {
+ span: self.span,
+ expr_ty: self.expr_ty,
+ cast_ty: self.cast_ty.to_owned(),
+ });
if self.expr_ty.references_error() {
err.downgrade_to_delayed_bug();
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 cae884ae8..8f4d81ec3 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
@@ -565,7 +565,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
/// type Map = HashMap<String>;
/// ```
fn suggest_adding_args(&self, err: &mut Diagnostic) {
- if self.gen_args.parenthesized {
+ if self.gen_args.parenthesized != hir::GenericArgsParentheses::No {
return;
}
@@ -962,7 +962,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let msg = format!(
"remove these {}generics",
- if self.gen_args.parenthesized { "parenthetical " } else { "" },
+ if self.gen_args.parenthesized == hir::GenericArgsParentheses::ParenSugar {
+ "parenthetical "
+ } else {
+ ""
+ },
);
err.span_suggestion(span, &msg, "", Applicability::MaybeIncorrect);
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 5d5c8ca60..0a45119ff 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
-use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
use std::ops::ControlFlow;
/// Defines the `TermsContext` basically houses an arena where we can
@@ -38,7 +38,7 @@ fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
solve::solve_constraints(constraints_cx)
}
-fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
+fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
// Skip items with no generics - there's nothing to infer in them.
if tcx.generics_of(item_def_id).count() == 0 {
return &[];
@@ -53,7 +53,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
| DefKind::Variant
| DefKind::Ctor(..) => {}
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
- return variance_of_opaque(tcx, item_def_id.expect_local());
+ return variance_of_opaque(tcx, item_def_id);
}
_ => {
// Variance not relevant.
@@ -64,7 +64,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
// Everything else must be inferred.
let crate_map = tcx.crate_variances(());
- crate_map.variances.get(&item_def_id).copied().unwrap_or(&[])
+ crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
}
#[instrument(level = "trace", skip(tcx), ret)]
@@ -112,10 +112,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
- if matches!(
- self.tcx.def_kind(*def_id),
- DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
- ) =>
+ if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
+ {
+ self.visit_opaque(*def_id, substs)
+ }
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
+ // at all for RPITITs.
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ if self.tcx.is_impl_trait_in_trait(*def_id) =>
{
self.visit_opaque(*def_id, substs)
}
@@ -148,7 +152,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.to_def_id());
+ 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);
debug!(?pred);
diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs
index 5feeb92d3..d57d05d76 100644
--- a/compiler/rustc_hir_analysis/src/variance/test.rs
+++ b/compiler/rustc_hir_analysis/src/variance/test.rs
@@ -1,14 +1,19 @@
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
+use crate::errors;
+
pub fn test_variance(tcx: TyCtxt<'_>) {
// For unit testing: check for a special "rustc_variance"
// attribute and report an error with various results if found.
for id in tcx.hir().items() {
- if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) {
+ if tcx.has_attr(id.owner_id, sym::rustc_variance) {
let variances_of = tcx.variances_of(id.owner_id);
- tcx.sess.struct_span_err(tcx.def_span(id.owner_id), format!("{variances_of:?}")).emit();
+ tcx.sess.emit_err(errors::VariancesOf {
+ span: tcx.def_span(id.owner_id),
+ variances_of: format!("{variances_of:?}"),
+ });
}
}
}