Skip to content

Commit 934624f

Browse files
committed
Auto merge of rust-lang#90945 - JohnTitor:rollup-wc35xss, r=JohnTitor
Rollup of 8 pull requests Successful merges: - rust-lang#86455 (check where-clause for explicit `Sized` before suggesting `?Sized`) - rust-lang#90801 (Normalize both arguments of `equate_normalized_input_or_output`) - rust-lang#90803 (Suggest `&str.chars()` on attempt to `&str.iter()`) - rust-lang#90819 (Fixes incorrect handling of TraitRefs when emitting suggestions.) - rust-lang#90910 (fix getting the discriminant of a zero-variant enum) - rust-lang#90925 (rustc_mir_build: reorder bindings) - rust-lang#90928 (Use a different server for checking clock drift) - rust-lang#90936 (Add a regression test for rust-lang#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

+38-22
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

+3-2
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

+16
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

+3-1
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

+1-1
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

+13
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

+21-38
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

+20
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

+3-19
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

+1-1
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
}

0 commit comments

Comments
 (0)