diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_attr_parsing/src/parser.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 5 |
3 files changed, 33 insertions, 17 deletions
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index a8a1460591c..e84bac945dc 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::DiagCtxtHandle; use rustc_hir::{self as hir, AttrPath}; use rustc_span::symbol::{Ident, kw, sym}; -use rustc_span::{ErrorGuaranteed, Span, Symbol}; +use rustc_span::{Span, Symbol}; pub struct SegmentIterator<'a> { offset: usize, @@ -176,7 +176,7 @@ impl<'a> ArgParser<'a> { pub enum MetaItemOrLitParser<'a> { MetaItemParser(MetaItemParser<'a>), Lit(MetaItemLit), - Err(Span, ErrorGuaranteed), + Err(Span), } impl<'a> MetaItemOrLitParser<'a> { @@ -186,7 +186,7 @@ impl<'a> MetaItemOrLitParser<'a> { generic_meta_item_parser.span() } MetaItemOrLitParser::Lit(meta_item_lit) => meta_item_lit.span, - MetaItemOrLitParser::Err(span, _) => *span, + MetaItemOrLitParser::Err(span) => *span, } } @@ -495,12 +495,9 @@ impl<'a> MetaItemListParserContext<'a> { // where the macro didn't expand to a literal. An error is already given // for this at this point, and then we do continue. This makes this path // reachable... - let e = self.dcx.span_delayed_bug( - *span, - "expr in place where literal is expected (builtin attr parsing)", - ); - - return Some(MetaItemOrLitParser::Err(*span, e)); + // NOTE: For backward compatibility we can't emit any error / delayed bug here (yet). + // See <https://github.com/rust-lang/rust/issues/140612> + return Some(MetaItemOrLitParser::Err(*span)); } else { self.next_path()? }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6..8be8ea1cc1c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_trait = regular_traits.into_iter().next(); - let mut needed_associated_types = vec![]; + // A stable ordering of associated types from the principal trait and all its + // supertraits. We use this to ensure that different substitutions of a trait + // don't result in `dyn Trait` types with different projections lists, which + // can be unsound: <https://github.com/rust-lang/rust/pull/136458>. + // We achieve a stable ordering by walking over the unsubstituted principal + // trait ref. + let mut ordered_associated_types = vec![]; + if let Some((principal_trait, ref spans)) = principal_trait { let principal_trait = principal_trait.map_bound(|trait_pred| { assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); @@ -171,16 +178,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(negative_bounds): Handle this correctly... let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); - needed_associated_types.extend( + ordered_associated_types.extend( tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() // We only care about associated types. .filter(|item| item.kind == ty::AssocKind::Type) // No RPITITs -- they're not dyn-compatible for now. .filter(|item| !item.is_impl_trait_in_trait()) - // If the associated type has a `where Self: Sized` bound, - // we do not need to constrain the associated type. - .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(|item| (item.def_id, trait_ref)), ); } @@ -252,14 +256,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // We compute the list of projection bounds taking the ordered associated types, + // and check if there was an entry in the collected `projection_bounds`. Those + // are computed by first taking the user-written associated types, then elaborating + // the principal trait ref, and only using those if there was no user-written. + // See note below about how we handle missing associated types with `Self: Sized`, + // which are not required to be provided, but are still used if they are provided. let mut missing_assoc_types = FxIndexSet::default(); - let projection_bounds: Vec<_> = needed_associated_types + let projection_bounds: Vec<_> = ordered_associated_types .into_iter() .filter_map(|key| { if let Some(assoc) = projection_bounds.get(&key) { Some(*assoc) } else { - missing_assoc_types.insert(key); + // If the associated type has a `where Self: Sized` bound, then + // we do not need to provide the associated type. This results in + // a `dyn Trait` type that has a different number of projection + // bounds, which may lead to type mismatches. + if !tcx.generics_require_sized_self(key.0) { + missing_assoc_types.insert(key); + } None } }) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 74a94d82784..c7193c6f6df 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -720,7 +720,10 @@ impl<'tcx> Ty<'tcx> { repr: DynKind, ) -> Ty<'tcx> { if cfg!(debug_assertions) { - let projection_count = obj.projection_bounds().count(); + let projection_count = obj + .projection_bounds() + .filter(|item| !tcx.generics_require_sized_self(item.item_def_id())) + .count(); let expected_count: usize = obj .principal_def_id() .into_iter() |
