Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 934624f

Browse files
committedNov 16, 2021
Auto merge of #90945 - JohnTitor:rollup-wc35xss, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #86455 (check where-clause for explicit `Sized` before suggesting `?Sized`) - #90801 (Normalize both arguments of `equate_normalized_input_or_output`) - #90803 (Suggest `&str.chars()` on attempt to `&str.iter()`) - #90819 (Fixes incorrect handling of TraitRefs when emitting suggestions.) - #90910 (fix getting the discriminant of a zero-variant enum) - #90925 (rustc_mir_build: reorder bindings) - #90928 (Use a different server for checking clock drift) - #90936 (Add a regression test for #80772) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents a2a7683 + c73b35e commit 934624f

File tree

22 files changed

+342
-96
lines changed

22 files changed

+342
-96
lines changed
 

‎compiler/rustc_borrowck/src/type_check/input_output.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
88
//! contain revealed `impl Trait` values).
99
10+
use crate::type_check::constraint_conversion::ConstraintConversion;
1011
use rustc_index::vec::Idx;
1112
use rustc_infer::infer::LateBoundRegionConversionTime;
1213
use rustc_middle::mir::*;
13-
use rustc_middle::traits::ObligationCause;
14-
use rustc_middle::ty::{self, Ty};
14+
use rustc_middle::ty::Ty;
1515
use rustc_span::Span;
16-
use rustc_trait_selection::traits::query::normalize::AtExt;
16+
use rustc_span::DUMMY_SP;
17+
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
18+
use rustc_trait_selection::traits::query::Fallible;
19+
use type_op::TypeOpOutput;
1720

1821
use crate::universal_regions::UniversalRegions;
1922

@@ -30,6 +33,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
3033
let (&normalized_output_ty, normalized_input_tys) =
3134
normalized_inputs_and_output.split_last().unwrap();
3235

36+
debug!(?normalized_output_ty);
37+
debug!(?normalized_input_tys);
38+
3339
let mir_def_id = body.source.def_id().expect_local();
3440

3541
// If the user explicitly annotated the input types, extract
@@ -75,10 +81,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
7581
.delay_span_bug(body.span, "found more normalized_input_ty than local_decls");
7682
break;
7783
}
84+
7885
// In MIR, argument N is stored in local N+1.
7986
let local = Local::new(argument_index + 1);
8087

8188
let mir_input_ty = body.local_decls[local].ty;
89+
8290
let mir_input_span = body.local_decls[local].source_info.span;
8391
self.equate_normalized_input_or_output(
8492
normalized_input_ty,
@@ -100,6 +108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
100108
// If the user explicitly annotated the input types, enforce those.
101109
let user_provided_input_ty =
102110
self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
111+
103112
self.equate_normalized_input_or_output(
104113
user_provided_input_ty,
105114
mir_input_ty,
@@ -167,30 +176,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
167176
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
168177
// like to normalize *before* inserting into `local_decls`, but
169178
// doing so ends up causing some other trouble.
170-
let b = match self
171-
.infcx
172-
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
173-
.normalize(b)
174-
{
175-
Ok(n) => {
176-
debug!("equate_inputs_and_outputs: {:?}", n);
177-
if n.obligations.iter().all(|o| {
178-
matches!(
179-
o.predicate.kind().skip_binder(),
180-
ty::PredicateKind::RegionOutlives(_)
181-
| ty::PredicateKind::TypeOutlives(_)
182-
)
183-
}) {
184-
n.value
185-
} else {
186-
b
187-
}
188-
}
179+
let b = match self.normalize_and_add_constraints(b) {
180+
Ok(n) => n,
189181
Err(_) => {
190182
debug!("equate_inputs_and_outputs: NoSolution");
191183
b
192184
}
193185
};
186+
194187
// Note: if we have to introduce new placeholders during normalization above, then we won't have
195188
// added those universes to the universe info, which we would want in `relate_tys`.
196189
if let Err(terr) =
@@ -207,4 +200,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
207200
}
208201
}
209202
}
203+
204+
pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
205+
let TypeOpOutput { output: norm_ty, constraints, .. } =
206+
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
207+
208+
debug!("{:?} normalized to {:?}", t, norm_ty);
209+
210+
for data in constraints.into_iter().collect::<Vec<_>>() {
211+
ConstraintConversion::new(
212+
self.infcx,
213+
&self.borrowck_context.universal_regions,
214+
&self.region_bound_pairs,
215+
Some(self.implicit_region_bound),
216+
self.param_env,
217+
Locations::All(DUMMY_SP),
218+
ConstraintCategory::Internal,
219+
&mut self.borrowck_context.constraints,
220+
)
221+
.convert_all(&*data);
222+
}
223+
224+
Ok(norm_ty)
225+
}
210226
}

‎compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,11 +893,11 @@ struct TypeChecker<'a, 'tcx> {
893893
}
894894

895895
struct BorrowCheckContext<'a, 'tcx> {
896-
universal_regions: &'a UniversalRegions<'tcx>,
896+
pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
897897
location_table: &'a LocationTable,
898898
all_facts: &'a mut Option<AllFacts>,
899899
borrow_set: &'a BorrowSet<'tcx>,
900-
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
900+
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
901901
upvars: &'a [Upvar<'tcx>],
902902
}
903903

@@ -1157,6 +1157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
11571157
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
11581158
}
11591159

1160+
#[instrument(skip(self, category), level = "debug")]
11601161
fn eq_types(
11611162
&mut self,
11621163
expected: Ty<'tcx>,

‎compiler/rustc_hir/src/hir.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,22 @@ pub struct WhereBoundPredicate<'hir> {
647647
pub bounds: GenericBounds<'hir>,
648648
}
649649

650+
impl WhereBoundPredicate<'hir> {
651+
/// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
652+
pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
653+
let path = match self.bounded_ty.kind {
654+
TyKind::Path(QPath::Resolved(None, path)) => path,
655+
_ => return false,
656+
};
657+
match path.res {
658+
Res::Def(DefKind::TyParam, def_id) | Res::SelfTy(Some(def_id), None) => {
659+
def_id == param_def_id
660+
}
661+
_ => false,
662+
}
663+
}
664+
}
665+
650666
/// A lifetime predicate (e.g., `'a: 'b + 'c`).
651667
#[derive(Debug, HashStable_Generic)]
652668
pub struct WhereRegionPredicate<'hir> {

‎compiler/rustc_middle/src/ty/sty.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2067,7 +2067,9 @@ impl<'tcx> TyS<'tcx> {
20672067
) -> Option<Discr<'tcx>> {
20682068
match self.kind() {
20692069
TyKind::Adt(adt, _) if adt.variants.is_empty() => {
2070-
bug!("discriminant_for_variant called on zero variant enum");
2070+
// This can actually happen during CTFE, see
2071+
// https://github.com/rust-lang/rust/issues/89765.
2072+
None
20712073
}
20722074
TyKind::Adt(adt, _) if adt.is_enum() => {
20732075
Some(adt.discriminant_for_variant(tcx, variant_index))

‎compiler/rustc_mir_build/src/build/matches/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1762,8 +1762,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17621762
) -> BlockAnd<()> {
17631763
let expr_span = expr.span;
17641764
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
1765-
let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
17661765
let wildcard = Pat::wildcard_from_ty(pat.ty);
1766+
let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
17671767
let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false);
17681768
let fake_borrow_temps = self.lower_match_tree(
17691769
block,

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
20092009
Some(param) => param,
20102010
_ => return,
20112011
};
2012+
let param_def_id = self.tcx.hir().local_def_id(param.hir_id).to_def_id();
2013+
let preds = generics.where_clause.predicates.iter();
2014+
let explicitly_sized = preds
2015+
.filter_map(|pred| match pred {
2016+
hir::WherePredicate::BoundPredicate(bp) => Some(bp),
2017+
_ => None,
2018+
})
2019+
.filter(|bp| bp.is_param_bound(param_def_id))
2020+
.flat_map(|bp| bp.bounds)
2021+
.any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait);
2022+
if explicitly_sized {
2023+
return;
2024+
}
20122025
debug!("maybe_suggest_unsized_generics: param={:?}", param);
20132026
match node {
20142027
hir::Node::Item(

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

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -706,36 +706,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
706706
}
707707

708708
let param_env = obligation.param_env;
709-
let trait_ref = poly_trait_ref.skip_binder();
710-
711-
let found_ty = trait_ref.self_ty();
712-
let found_ty_str = found_ty.to_string();
713-
let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty);
714-
let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]);
715-
let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty);
716-
let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]);
717709

718710
// Try to apply the original trait binding obligation by borrowing.
719-
let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
720-
new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
721-
expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
711+
let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
722712
blacklist: &[DefId]|
723713
-> bool {
724-
if blacklist.contains(&expected_trait_ref.def_id()) {
714+
if blacklist.contains(&old_ref.def_id()) {
725715
return false;
726716
}
727717

728-
let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
729-
ObligationCause::dummy(),
730-
param_env,
731-
new_imm_trait_ref.without_const().to_predicate(self.tcx),
732-
));
733-
734-
let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
735-
ObligationCause::dummy(),
736-
param_env,
737-
new_mut_trait_ref.without_const().to_predicate(self.tcx),
738-
));
718+
let orig_ty = old_ref.self_ty().skip_binder();
719+
let mk_result = |new_ty| {
720+
let new_ref = old_ref.rebind(ty::TraitRef::new(
721+
old_ref.def_id(),
722+
self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]),
723+
));
724+
self.predicate_must_hold_modulo_regions(&Obligation::new(
725+
ObligationCause::dummy(),
726+
param_env,
727+
new_ref.without_const().to_predicate(self.tcx),
728+
))
729+
};
730+
let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty));
731+
let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty));
739732

740733
if imm_result || mut_result {
741734
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
@@ -747,8 +740,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
747740

748741
let msg = format!(
749742
"the trait bound `{}: {}` is not satisfied",
750-
found_ty_str,
751-
expected_trait_ref.print_only_trait_path(),
743+
orig_ty.to_string(),
744+
old_ref.print_only_trait_path(),
752745
);
753746
if has_custom_message {
754747
err.note(&msg);
@@ -764,7 +757,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
764757
span,
765758
&format!(
766759
"expected an implementor of trait `{}`",
767-
expected_trait_ref.print_only_trait_path(),
760+
old_ref.print_only_trait_path(),
768761
),
769762
);
770763

@@ -807,21 +800,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
807800
};
808801

809802
if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
810-
let expected_trait_ref = obligation.parent_trait_ref;
811-
let new_imm_trait_ref = poly_trait_ref
812-
.rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs));
813-
let new_mut_trait_ref = poly_trait_ref
814-
.rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs));
815-
return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]);
803+
try_borrowing(obligation.parent_trait_ref, &[])
816804
} else if let ObligationCauseCode::BindingObligation(_, _)
817805
| ObligationCauseCode::ItemObligation(_) = &*code
818806
{
819-
return try_borrowing(
820-
poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)),
821-
poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)),
822-
*poly_trait_ref,
823-
&never_suggest_borrow[..],
824-
);
807+
try_borrowing(*poly_trait_ref, &never_suggest_borrow[..])
825808
} else {
826809
false
827810
}

‎compiler/rustc_typeck/src/check/method/suggest.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
478478
let mut label_span_not_found = || {
479479
if unsatisfied_predicates.is_empty() {
480480
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
481+
let is_string_or_ref_str = match actual.kind() {
482+
ty::Ref(_, ty, _) => {
483+
ty.is_str()
484+
|| matches!(
485+
ty.kind(),
486+
ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did)
487+
)
488+
}
489+
ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did),
490+
_ => false,
491+
};
492+
if is_string_or_ref_str && item_name.name == sym::iter {
493+
err.span_suggestion_verbose(
494+
item_name.span,
495+
"because of the in-memory representation of `&str`, to obtain \
496+
an `Iterator` over each of its codepoint use method `chars`",
497+
String::from("chars"),
498+
Applicability::MachineApplicable,
499+
);
500+
}
481501
if let ty::Adt(adt, _) = rcvr_ty.kind() {
482502
let mut inherent_impls_candidate = self
483503
.tcx

‎compiler/rustc_typeck/src/collect.rs

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_data_structures::captures::Captures;
2828
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
2929
use rustc_errors::{struct_span_err, Applicability};
3030
use rustc_hir as hir;
31-
use rustc_hir::def::{CtorKind, DefKind, Res};
31+
use rustc_hir::def::{CtorKind, DefKind};
3232
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
3333
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
3434
use rustc_hir::weak_lang_items;
@@ -668,6 +668,7 @@ impl ItemCtxt<'tcx> {
668668
})
669669
.flat_map(|b| predicates_from_bound(self, ty, b));
670670

671+
let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
671672
let from_where_clauses = ast_generics
672673
.where_clause
673674
.predicates
@@ -677,7 +678,7 @@ impl ItemCtxt<'tcx> {
677678
_ => None,
678679
})
679680
.flat_map(|bp| {
680-
let bt = if is_param(self.tcx, bp.bounded_ty, param_id) {
681+
let bt = if bp.is_param_bound(param_def_id) {
681682
Some(ty)
682683
} else if !only_self_bounds.0 {
683684
Some(self.to_ty(bp.bounded_ty))
@@ -714,23 +715,6 @@ impl ItemCtxt<'tcx> {
714715
}
715716
}
716717

717-
/// Tests whether this is the AST for a reference to the type
718-
/// parameter with ID `param_id`. We use this so as to avoid running
719-
/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
720-
/// conversion of the type to avoid inducing unnecessary cycles.
721-
fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty<'_>, param_id: hir::HirId) -> bool {
722-
if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ast_ty.kind {
723-
match path.res {
724-
Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => {
725-
def_id == tcx.hir().local_def_id(param_id).to_def_id()
726-
}
727-
_ => false,
728-
}
729-
} else {
730-
false
731-
}
732-
}
733-
734718
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
735719
let it = tcx.hir().item(item_id);
736720
debug!("convert: item {} with id {}", it.ident, it.hir_id());

‎src/ci/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ datecheck() {
117117
echo -n " local time: "
118118
date
119119
echo -n " network time: "
120-
curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \
120+
curl -fs --head http://ci-caches.rust-lang.org | grep ^Date: \
121121
| sed 's/Date: //g' || true
122122
echo "== end clock drift check =="
123123
}

‎src/test/ui/borrowck/issue-80772.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
3+
trait SomeTrait {}
4+
5+
pub struct Exhibit {
6+
constant: usize,
7+
factory: fn(&usize) -> Box<dyn SomeTrait>,
8+
}
9+
10+
pub const A_CONSTANT: &[Exhibit] = &[
11+
Exhibit {
12+
constant: 1,
13+
factory: |_| unimplemented!(),
14+
},
15+
Exhibit {
16+
constant: "Hello world".len(),
17+
factory: |_| unimplemented!(),
18+
},
19+
];
20+
21+
fn main() {}

‎src/test/ui/consts/const_discriminant.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ enum SingleVariant {
2525

2626
const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);
2727

28+
pub const TEST_VOID: () = {
29+
// This is UB, but CTFE does not check validity so it does not detect this.
30+
// This is a regression test for https://github.com/rust-lang/rust/issues/89765.
31+
unsafe { std::mem::discriminant(&*(&() as *const () as *const Void)); };
32+
};
33+
34+
2835
fn main() {
2936
assert_eq!(TEST_A, TEST_A_OTHER);
3037
assert_eq!(TEST_A, discriminant(black_box(&Test::A(17))));

‎src/test/ui/derives/deriving-copyclone.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: the trait bound `C: Copy` is not satisfied
1+
error[E0277]: the trait bound `B<C>: Copy` is not satisfied
22
--> $DIR/deriving-copyclone.rs:31:13
33
|
44
LL | is_copy(B { a: 1, b: C });
@@ -22,7 +22,7 @@ help: consider borrowing here
2222
LL | is_copy(&B { a: 1, b: C });
2323
| +
2424

25-
error[E0277]: the trait bound `C: Clone` is not satisfied
25+
error[E0277]: the trait bound `B<C>: Clone` is not satisfied
2626
--> $DIR/deriving-copyclone.rs:32:14
2727
|
2828
LL | is_clone(B { a: 1, b: C });
@@ -46,7 +46,7 @@ help: consider borrowing here
4646
LL | is_clone(&B { a: 1, b: C });
4747
| +
4848

49-
error[E0277]: the trait bound `D: Copy` is not satisfied
49+
error[E0277]: the trait bound `B<D>: Copy` is not satisfied
5050
--> $DIR/deriving-copyclone.rs:35:13
5151
|
5252
LL | is_copy(B { a: 1, b: D });
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
use std::marker::PhantomData;
6+
7+
trait Family: Sized {
8+
type Item<'a>;
9+
10+
fn apply_all<F>(&self, f: F)
11+
where
12+
F: FamilyItemFn<Self> { }
13+
}
14+
15+
struct Array<T>(PhantomData<T>);
16+
17+
impl<T: 'static> Family for Array<T> {
18+
type Item<'a> = &'a T;
19+
}
20+
21+
trait FamilyItemFn<T: Family> {
22+
fn apply(&self, item: T::Item<'_>);
23+
}
24+
25+
impl<T, F> FamilyItemFn<T> for F
26+
where
27+
T: Family,
28+
for<'a> F: Fn(T::Item<'a>)
29+
{
30+
fn apply(&self, item: T::Item<'_>) {
31+
(*self)(item);
32+
}
33+
}
34+
35+
fn process<T: 'static>(array: Array<T>) {
36+
// Works
37+
array.apply_all(|x: &T| { });
38+
39+
// ICE: NoSolution
40+
array.apply_all(|x: <Array<T> as Family>::Item<'_>| { });
41+
}
42+
43+
fn main() {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//check-pass
2+
3+
#![feature(generic_associated_types)]
4+
5+
trait Yokeable<'a>: 'static {
6+
type Output: 'a;
7+
}
8+
9+
trait IsCovariant<'a> {}
10+
11+
struct Yoke<Y: for<'a> Yokeable<'a>> {
12+
data: Y,
13+
}
14+
15+
impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
16+
fn project<Y2: for<'a> Yokeable<'a>>(&self, _f: for<'a> fn(<Y as Yokeable<'a>>::Output, &'a ())
17+
-> <Y2 as Yokeable<'a>>::Output) -> Yoke<Y2> {
18+
19+
unimplemented!()
20+
}
21+
}
22+
23+
fn _upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
24+
Y: for<'a> Yokeable<'a>,
25+
for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
26+
{
27+
x.project(|data, _| {
28+
Box::new(data)
29+
})
30+
}
31+
32+
33+
impl<'a> Yokeable<'a> for Box<dyn IsCovariant<'static> + 'static> {
34+
type Output = Box<dyn IsCovariant<'a> + 'a>;
35+
}
36+
37+
fn main() {}

‎src/test/ui/suggest-using-chars.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub fn main() {
2+
let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope
3+
let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope
4+
let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope
5+
let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope
6+
let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope
7+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0599]: no method named `iter` found for reference `&'static str` in the current scope
2+
--> $DIR/suggest-using-chars.rs:2:19
3+
|
4+
LL | let _ = "foo".iter();
5+
| ^^^^ method not found in `&'static str`
6+
|
7+
help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
8+
|
9+
LL | let _ = "foo".chars();
10+
| ~~~~~
11+
12+
error[E0599]: no method named `foo` found for reference `&'static str` in the current scope
13+
--> $DIR/suggest-using-chars.rs:3:19
14+
|
15+
LL | let _ = "foo".foo();
16+
| ^^^ method not found in `&'static str`
17+
18+
error[E0599]: no method named `iter` found for struct `String` in the current scope
19+
--> $DIR/suggest-using-chars.rs:4:33
20+
|
21+
LL | let _ = String::from("bar").iter();
22+
| ^^^^ method not found in `String`
23+
|
24+
help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
25+
|
26+
LL | let _ = String::from("bar").chars();
27+
| ~~~~~
28+
29+
error[E0599]: no method named `iter` found for reference `&String` in the current scope
30+
--> $DIR/suggest-using-chars.rs:5:36
31+
|
32+
LL | let _ = (&String::from("bar")).iter();
33+
| ^^^^ method not found in `&String`
34+
|
35+
help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
36+
|
37+
LL | let _ = (&String::from("bar")).chars();
38+
| ~~~~~
39+
40+
error[E0599]: no method named `iter` found for type `{integer}` in the current scope
41+
--> $DIR/suggest-using-chars.rs:6:15
42+
|
43+
LL | let _ = 0.iter();
44+
| ^^^^ method not found in `{integer}`
45+
46+
error: aborting due to 5 previous errors
47+
48+
For more information about this error, try `rustc --explain E0599`.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Regression test for #85945: Don't suggest `?Sized` bound if an explicit
2+
// `Sized` bound is already in a `where` clause.
3+
fn foo<T>(_: &T) where T: Sized {}
4+
fn bar() { foo(""); }
5+
//~^ERROR the size for values of type
6+
7+
pub fn main() {
8+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: the size for values of type `str` cannot be known at compilation time
2+
--> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16
3+
|
4+
LL | fn bar() { foo(""); }
5+
| --- ^^ doesn't have a size known at compile-time
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Sized` is not implemented for `str`
10+
note: required by a bound in `foo`
11+
--> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8
12+
|
13+
LL | fn foo<T>(_: &T) where T: Sized {}
14+
| ^ required by this bound in `foo`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.

‎src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ LL | is_send(Box::new(TestType));
6565
| |
6666
| required by a bound introduced by this call
6767
|
68-
= note: the trait bound `dummy2::TestType: Send` is not satisfied
68+
= note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied
6969
= note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>`
7070
= note: required because it appears within the type `Box<dummy2::TestType>`
7171
note: required by a bound in `is_send`
@@ -104,11 +104,11 @@ error[E0277]: `main::TestType` cannot be sent between threads safely
104104
--> $DIR/negated-auto-traits-error.rs:66:13
105105
|
106106
LL | is_sync(Outer2(TestType));
107-
| ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Sync`
107+
| ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely
108108
| |
109109
| required by a bound introduced by this call
110110
|
111-
= note: the trait bound `main::TestType: Sync` is not satisfied
111+
= help: the trait `Send` is not implemented for `main::TestType`
112112
note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>`
113113
--> $DIR/negated-auto-traits-error.rs:14:22
114114
|
@@ -119,12 +119,6 @@ note: required by a bound in `is_sync`
119119
|
120120
LL | fn is_sync<T: Sync>(_: T) {}
121121
| ^^^^ required by this bound in `is_sync`
122-
help: consider borrowing here
123-
|
124-
LL | is_sync(&Outer2(TestType));
125-
| +
126-
LL | is_sync(&mut Outer2(TestType));
127-
| ++++
128122

129123
error: aborting due to 7 previous errors
130124

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Do not suggest referencing the parameter to `check`
2+
3+
trait Marker<T> {}
4+
5+
impl<T> Marker<i32> for T {}
6+
7+
pub fn check<T: Marker<u32>>(_: T) {}
8+
9+
pub fn main() {
10+
check::<()>(()); //~ ERROR [E0277]
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0277]: the trait bound `(): Marker<u32>` is not satisfied
2+
--> $DIR/issue-90804-incorrect-reference-suggestion.rs:10:17
3+
|
4+
LL | check::<()>(());
5+
| ----------- ^^ the trait `Marker<u32>` is not implemented for `()`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: required by a bound in `check`
10+
--> $DIR/issue-90804-incorrect-reference-suggestion.rs:7:17
11+
|
12+
LL | pub fn check<T: Marker<u32>>(_: T) {}
13+
| ^^^^^^^^^^^ required by this bound in `check`
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)
Please sign in to comment.