Skip to content

Commit c846d9f

Browse files
committed
Tweak assoc type obligation spans
* Mention where implicit `Sized` obligations come from on E0277 * New predicate field for `Sized` obligations * Suggest `T: ?Sized` in more places
1 parent 06a6674 commit c846d9f

File tree

75 files changed

+357
-157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+357
-157
lines changed

compiler/rustc_borrowck/src/type_check/canonical.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
9595
trait_ref,
9696
constness: ty::BoundConstness::NotConst,
9797
polarity: ty::ImplPolarity::Positive,
98+
implicit: ty::ImplicitBound::No,
9899
}))),
99100
locations,
100101
category,

compiler/rustc_const_eval/src/transform/check_consts/check.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
813813
trait_ref,
814814
constness: ty::BoundConstness::ConstIfConst,
815815
polarity: ty::ImplPolarity::Positive,
816+
implicit: ty::ImplicitBound::No,
816817
}),
817818
);
818819

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ impl Qualif for NeedsNonConstDrop {
162162
trait_ref,
163163
constness: ty::BoundConstness::ConstIfConst,
164164
polarity: ty::ImplPolarity::Positive,
165+
implicit: ty::ImplicitBound::No,
165166
}),
166167
);
167168

compiler/rustc_infer/src/infer/outlives/obligations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
103103
cause.span,
104104
sup_type,
105105
match cause.code.peel_derives() {
106-
ObligationCauseCode::BindingObligation(_, span) => Some(*span),
106+
ObligationCauseCode::BindingObligation(_, span)
107+
| ObligationCauseCode::ImplicitSizedObligation(_, span) => Some(*span),
107108
_ => None,
108109
},
109110
)

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ pub enum ObligationCauseCode<'tcx> {
204204
/// Like `ItemObligation`, but with extra detail on the source of the obligation.
205205
BindingObligation(DefId, Span),
206206

207+
/// Like `ItemObligation`, but with extra detail on the source of the obligation.
208+
ImplicitSizedObligation(DefId, Span),
209+
207210
/// A type like `&'a T` is WF only if `T: 'a`.
208211
ReferenceOutlivesReferent(Ty<'tcx>),
209212

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,25 @@ pub struct ImplHeader<'tcx> {
165165
pub predicates: Vec<Predicate<'tcx>>,
166166
}
167167

168+
#[derive(
169+
Copy,
170+
Clone,
171+
PartialEq,
172+
Eq,
173+
Hash,
174+
TyEncodable,
175+
TyDecodable,
176+
HashStable,
177+
Debug,
178+
TypeFoldable
179+
)]
180+
pub enum ImplicitBound {
181+
/// `T: Trait`
182+
No,
183+
/// implicit `T: Sized`
184+
Yes,
185+
}
186+
168187
#[derive(
169188
Copy,
170189
Clone,
@@ -518,13 +537,17 @@ impl<'tcx> Predicate<'tcx> {
518537
.inner
519538
.kind
520539
.map_bound(|kind| match kind {
521-
PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => {
522-
Some(PredicateKind::Trait(TraitPredicate {
523-
trait_ref,
524-
constness,
525-
polarity: polarity.flip()?,
526-
}))
527-
}
540+
PredicateKind::Trait(TraitPredicate {
541+
trait_ref,
542+
constness,
543+
polarity,
544+
implicit,
545+
}) => Some(PredicateKind::Trait(TraitPredicate {
546+
trait_ref,
547+
constness,
548+
polarity: polarity.flip()?,
549+
implicit,
550+
})),
528551

529552
_ => None,
530553
})
@@ -729,6 +752,8 @@ pub struct TraitPredicate<'tcx> {
729752
pub constness: BoundConstness,
730753

731754
pub polarity: ImplPolarity,
755+
756+
pub implicit: ImplicitBound,
732757
}
733758

734759
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
@@ -1425,6 +1450,7 @@ impl PolyTraitRef<'tcx> {
14251450
trait_ref,
14261451
constness,
14271452
polarity: ty::ImplPolarity::Positive,
1453+
implicit: ty::ImplicitBound::No,
14281454
})
14291455
}
14301456
#[inline]

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,21 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
788788
}
789789
}
790790

791+
impl<'tcx> Relate<'tcx> for ty::ImplicitBound {
792+
fn relate<R: TypeRelation<'tcx>>(
793+
_relation: &mut R,
794+
a: ty::ImplicitBound,
795+
b: ty::ImplicitBound,
796+
) -> RelateResult<'tcx, ty::ImplicitBound> {
797+
match (a, b) {
798+
(ty::ImplicitBound::No, ty::ty::ImplicitBound::No) => Ok(ty::ImplicitBound::No),
799+
(ty::ImplicitBound::Yes, ty::ty::ImplicitBound::Yes)
800+
| (ty::ImplicitBound::Yes, ty::ty::ImplicitBound::No)
801+
| (ty::ImplicitBound::No, ty::ty::ImplicitBound::Yes) => Ok(ty::ImplicitBound::Yes),
802+
}
803+
}
804+
}
805+
791806
impl<'tcx> Relate<'tcx> for ty::ImplPolarity {
792807
fn relate<R: TypeRelation<'tcx>>(
793808
relation: &mut R,
@@ -812,6 +827,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
812827
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
813828
constness: relation.relate(a.constness, b.constness)?,
814829
polarity: relation.relate(a.polarity, b.polarity)?,
830+
implicit: relation.relate(a.implicit, b.implicit)?,
815831
})
816832
}
817833
}

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
369369
trait_ref,
370370
constness: self.constness,
371371
polarity: self.polarity,
372+
implicit: ty::ImplicitBound::No,
372373
})
373374
}
374375
}

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
944944
trait_ref,
945945
constness: ty::BoundConstness::NotConst,
946946
polarity: ty::ImplPolarity::Positive,
947+
implicit: ty::ImplicitBound::No,
947948
})
948949
}
949950
}

compiler/rustc_privacy/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ where
128128
trait_ref,
129129
constness: _,
130130
polarity: _,
131+
implicit: _,
131132
}) => self.visit_trait(trait_ref),
132133
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
133134
ty.visit_with(self)?;

compiler/rustc_trait_selection/src/traits/auto_trait.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ impl AutoTraitFinder<'tcx> {
290290
constness: ty::BoundConstness::NotConst,
291291
// Auto traits are positive
292292
polarity: ty::ImplPolarity::Positive,
293+
implicit: ty::ImplicitBound::No,
293294
}));
294295

295296
let computed_preds = param_env.caller_bounds().iter();

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
13071307
obligation.cause.code.peel_derives(),
13081308
ObligationCauseCode::ItemObligation(_)
13091309
| ObligationCauseCode::BindingObligation(_, _)
1310+
| ObligationCauseCode::ImplicitSizedObligation(_, _)
13101311
| ObligationCauseCode::ObjectCastObligation(_)
13111312
| ObligationCauseCode::OpaqueType
13121313
);
@@ -1702,7 +1703,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
17021703
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
17031704
} else if let (
17041705
Ok(ref snippet),
1705-
ObligationCauseCode::BindingObligation(ref def_id, _),
1706+
ObligationCauseCode::BindingObligation(ref def_id, _)
1707+
| ObligationCauseCode::ImplicitSizedObligation(ref def_id, _),
17061708
) =
17071709
(self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
17081710
{
@@ -2005,7 +2007,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
20052007
{
20062008
(
20072009
ty::PredicateKind::Trait(pred),
2008-
&ObligationCauseCode::BindingObligation(item_def_id, span),
2010+
&ObligationCauseCode::BindingObligation(item_def_id, span)
2011+
| &ObligationCauseCode::ImplicitSizedObligation(item_def_id, span),
20092012
) => (pred, item_def_id, span),
20102013
_ => return,
20112014
};

compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
141141
}
142142

143143
if let ObligationCauseCode::ItemObligation(item)
144-
| ObligationCauseCode::BindingObligation(item, _) = obligation.cause.code
144+
| ObligationCauseCode::BindingObligation(item, _)
145+
| ObligationCauseCode::ImplicitSizedObligation(item, _) = obligation.cause.code
145146
{
146147
// FIXME: maybe also have some way of handling methods
147148
// from other traits? That would require name resolution,

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
802802
if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
803803
try_borrowing(obligation.parent_trait_ref, &[])
804804
} else if let ObligationCauseCode::BindingObligation(_, _)
805+
| ObligationCauseCode::ImplicitSizedObligation(..)
805806
| ObligationCauseCode::ItemObligation(_) = &*code
806807
{
807808
try_borrowing(*poly_trait_ref, &never_suggest_borrow)
@@ -1961,6 +1962,62 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
19611962
// We hold the `DefId` of the item introducing the obligation, but displaying it
19621963
// doesn't add user usable information. It always point at an associated item.
19631964
}
1965+
ObligationCauseCode::ImplicitSizedObligation(item_def_id, span) => {
1966+
let item_name = tcx.def_path_str(item_def_id);
1967+
let mut sp: MultiSpan = span.into();
1968+
match self.tcx.hir().get_if_local(item_def_id) {
1969+
Some(hir::Node::TraitItem(hir::TraitItem {
1970+
kind: hir::TraitItemKind::Type(bounds, _),
1971+
ident,
1972+
..
1973+
})) => {
1974+
sp.push_span_label(
1975+
span,
1976+
format!("required by associated type `{}`", item_name),
1977+
);
1978+
err.span_note(sp, "associated types have an implicit `Sized` obligation");
1979+
1980+
let sized_trait = self.tcx.lang_items().sized_trait();
1981+
if bounds.len() == 0 {
1982+
err.span_suggestion_verbose(
1983+
ident.span.shrink_to_hi(),
1984+
"consider relaxing the `Sized` obligation",
1985+
": ?Sized".to_string(),
1986+
Applicability::MaybeIncorrect,
1987+
);
1988+
} else if bounds.iter().all(|bound| {
1989+
bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait
1990+
}) {
1991+
err.span_suggestion_verbose(
1992+
bounds.iter().last().unwrap().span().shrink_to_hi(),
1993+
"consider relaxing the `Sized` obligation",
1994+
" + ?Sized".to_string(),
1995+
Applicability::MaybeIncorrect,
1996+
);
1997+
}
1998+
}
1999+
Some(hir::Node::ImplItem(hir::ImplItem {
2000+
kind: hir::ImplItemKind::TyAlias(_),
2001+
..
2002+
})) => {
2003+
let msg = "associated types on `impl` blocks for types, have an implicit \
2004+
mandatory `Sized` obligation; associated types from `trait`s can be \
2005+
relaxed to `?Sized`";
2006+
sp.push_span_label(
2007+
span,
2008+
format!("required by associated type `{}`", item_name),
2009+
);
2010+
err.span_note(sp, msg);
2011+
}
2012+
_ => {
2013+
sp.push_span_label(
2014+
span,
2015+
format!("required by this bound in `{}`", item_name),
2016+
);
2017+
err.span_note(sp, "type parameters have an implicit `Sized` obligation");
2018+
}
2019+
}
2020+
}
19642021
ObligationCauseCode::BindingObligation(item_def_id, span) => {
19652022
let item_name = tcx.def_path_str(item_def_id);
19662023
let mut multispan = MultiSpan::from(span);

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot(
826826
trait_ref,
827827
constness: ty::BoundConstness::NotConst,
828828
polarity: ty::ImplPolarity::Positive,
829+
implicit: ty::ImplicitBound::No,
829830
}),
830831
);
831832

compiler/rustc_trait_selection/src/traits/relationships.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub(crate) fn update<'tcx, T>(
4545
trait_ref,
4646
constness: predicate.constness,
4747
polarity: predicate.polarity,
48+
implicit: predicate.implicit,
4849
})
4950
})
5051
.to_predicate(infcx.tcx),

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
935935
},
936936
constness: ty::BoundConstness::NotConst,
937937
polarity: ty::ImplPolarity::Positive,
938+
implicit: ty::ImplicitBound::No,
938939
}));
939940
copy_obligation.recursion_depth = depth + 1;
940941
self.assemble_candidates_from_impls(&copy_obligation, &mut new_candidates);
@@ -951,6 +952,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
951952
},
952953
constness: ty::BoundConstness::ConstIfConst,
953954
polarity: ty::ImplPolarity::Positive,
955+
implicit: ty::ImplicitBound::No,
954956
}));
955957

956958
let const_drop_stack = self.push_stack(obligation_stack.list(), &const_drop_obligation);

compiler/rustc_trait_selection/src/traits/util.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,13 @@ pub fn predicates_for_generics<'tcx>(
236236
traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new(
237237
cause.span,
238238
cause.body_id,
239-
traits::BindingObligation(def_id, span),
239+
match predicate.kind().skip_binder() {
240+
ty::PredicateKind::Trait(ty::TraitPredicate {
241+
implicit: ty::ImplicitBound::Yes,
242+
..
243+
}) => traits::ImplicitSizedObligation(def_id, span),
244+
_ => traits::BindingObligation(def_id, span),
245+
},
240246
),
241247
_ => cause.clone(),
242248
};

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
710710

711711
iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
712712
.map(|((pred, span), origin_def_id)| {
713-
let code = if span.is_dummy() {
714-
traits::MiscObligation
715-
} else {
716-
traits::BindingObligation(origin_def_id, span)
713+
let code = match pred.kind().skip_binder() {
714+
_ if span.is_dummy() => traits::MiscObligation,
715+
ty::PredicateKind::Trait(ty::TraitPredicate {
716+
implicit: ty::ImplicitBound::Yes,
717+
..
718+
}) => traits::ImplicitSizedObligation(origin_def_id, span),
719+
_ => traits::BindingObligation(origin_def_id, span),
717720
};
718721
let cause = self.cause(code);
719722
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)

compiler/rustc_typeck/src/bounds.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,17 @@ impl<'tcx> Bounds<'tcx> {
5656
// If it could be sized, and is, add the `Sized` predicate.
5757
let sized_predicate = self.implicitly_sized.and_then(|span| {
5858
tcx.lang_items().sized_trait().map(|sized| {
59-
let trait_ref = ty::Binder::dummy(ty::TraitRef {
60-
def_id: sized,
61-
substs: tcx.mk_substs_trait(param_ty, &[]),
62-
});
63-
(trait_ref.without_const().to_predicate(tcx), span)
59+
let pred = ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
60+
trait_ref: ty::TraitRef {
61+
def_id: sized,
62+
substs: tcx.mk_substs_trait(param_ty, &[]),
63+
},
64+
constness: ty::BoundConstness::NotConst,
65+
polarity: ty::ImplPolarity::Positive,
66+
implicit: ty::ImplicitBound::Yes,
67+
}))
68+
.to_predicate(tcx);
69+
(pred, span)
6470
})
6571
});
6672

compiler/rustc_typeck/src/check/_match.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
531531
},
532532
constness: t.constness,
533533
polarity: t.polarity,
534+
implicit: t.implicit,
534535
}));
535536
let obl = Obligation::new(
536537
o.cause.clone(),

compiler/rustc_typeck/src/check/cast.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -625,8 +625,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
625625
fcx.ty_to_string(t_cast)
626626
))
627627
.help(&format!(
628-
"cast can be replaced by coercion; this might \
629-
require {}a temporary variable",
628+
"cast can be replaced by coercion; this might require {}a temporary variable",
630629
type_asc_or
631630
))
632631
.emit();

0 commit comments

Comments
 (0)