Skip to content

Commit f82bfac

Browse files
authored
Merge branch 'rust-lang:master' into c-string-eq-c-str
2 parents 4acd142 + ed49386 commit f82bfac

20 files changed

+262
-109
lines changed

compiler/rustc_borrowck/src/type_check/liveness/trace.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ use rustc_index::bit_set::DenseBitSet;
33
use rustc_index::interval::IntervalSet;
44
use rustc_infer::infer::canonical::QueryRegionConstraints;
55
use rustc_infer::infer::outlives::for_liveness;
6-
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
6+
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
7+
use rustc_middle::span_bug;
78
use rustc_middle::traits::query::DropckOutlivesResult;
89
use rustc_middle::ty::relate::Relate;
910
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
1011
use rustc_mir_dataflow::ResultsCursor;
1112
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
1213
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
1314
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
14-
use rustc_span::DUMMY_SP;
15+
use rustc_span::{DUMMY_SP, Span};
16+
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
17+
use rustc_trait_selection::traits::ObligationCtxt;
18+
use rustc_trait_selection::traits::query::dropck_outlives;
1519
use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
1620
use tracing::debug;
1721

@@ -162,9 +166,10 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
162166
fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
163167
for local in boring_locals {
164168
let local_ty = self.cx.body.local_decls[local].ty;
169+
let local_span = self.cx.body.local_decls[local].source_info.span;
165170
let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
166171
let typeck = &self.cx.typeck;
167-
move || LivenessContext::compute_drop_data(typeck, local_ty)
172+
move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
168173
});
169174

170175
drop_data.dropck_result.report_overflows(
@@ -522,9 +527,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
522527
values::pretty_print_points(self.location_map, live_at.iter()),
523528
);
524529

530+
let local_span = self.body.local_decls()[dropped_local].source_info.span;
525531
let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
526532
let typeck = &self.typeck;
527-
move || Self::compute_drop_data(typeck, dropped_ty)
533+
move || Self::compute_drop_data(typeck, dropped_ty, local_span)
528534
});
529535

530536
if let Some(data) = &drop_data.region_constraint_data {
@@ -589,19 +595,44 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
589595
}
590596
}
591597

592-
fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> {
593-
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
598+
fn compute_drop_data(
599+
typeck: &TypeChecker<'_, 'tcx>,
600+
dropped_ty: Ty<'tcx>,
601+
span: Span,
602+
) -> DropData<'tcx> {
603+
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty);
604+
605+
let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
594606

595-
match typeck
596-
.infcx
597-
.param_env
598-
.and(DropckOutlives { dropped_ty })
599-
.fully_perform(typeck.infcx, DUMMY_SP)
600-
{
607+
match op.fully_perform(typeck.infcx, DUMMY_SP) {
601608
Ok(TypeOpOutput { output, constraints, .. }) => {
602609
DropData { dropck_result: output, region_constraint_data: constraints }
603610
}
604-
Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
611+
Err(_) => {
612+
// We don't run dropck on HIR, and dropck looks inside fields of
613+
// types, so there's no guarantee that it succeeds. We also
614+
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
615+
// because it comes from delay_span_bug.
616+
let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
617+
let errors =
618+
match dropck_outlives::compute_dropck_outlives_with_errors(&ocx, op, span) {
619+
Ok(_) => ocx.select_all_or_error(),
620+
Err(e) => {
621+
if e.is_empty() {
622+
ocx.select_all_or_error()
623+
} else {
624+
e
625+
}
626+
}
627+
};
628+
629+
if !errors.is_empty() {
630+
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
631+
} else {
632+
span_bug!(span, "Rerunning drop data query produced no error.");
633+
}
634+
DropData { dropck_result: Default::default(), region_constraint_data: None }
635+
}
605636
}
606637
}
607638
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ rustc_queries! {
802802

803803
query adt_dtorck_constraint(
804804
key: DefId
805-
) -> Result<&'tcx DropckConstraint<'tcx>, NoSolution> {
805+
) -> &'tcx DropckConstraint<'tcx> {
806806
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
807807
}
808808

compiler/rustc_mir_transform/src/elaborate_drop.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,21 @@ where
266266
let tcx = self.tcx();
267267

268268
assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
269-
let field_ty =
270-
tcx.normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args));
269+
// The type error for normalization may have been in dropck: see
270+
// `compute_drop_data` in rustc_borrowck, in which case we wouldn't have
271+
// deleted the MIR body and could have an error here as well.
272+
let field_ty = match tcx
273+
.try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args))
274+
{
275+
Ok(t) => t,
276+
Err(_) => Ty::new_error(
277+
self.tcx(),
278+
self.elaborator
279+
.body()
280+
.tainted_by_errors
281+
.expect("Error in drop elaboration not found by dropck."),
282+
),
283+
};
271284

272285
(tcx.mk_place_field(base_place, field, field_ty), subpath)
273286
})

compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet;
22
use rustc_infer::traits::query::type_op::DropckOutlives;
33
use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
44
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
5-
use rustc_span::{DUMMY_SP, Span};
5+
use rustc_span::Span;
66
use tracing::{debug, instrument};
77

8+
use crate::solve::NextSolverError;
89
use crate::traits::query::NoSolution;
910
use crate::traits::query::normalize::QueryNormalizeExt;
10-
use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
11+
use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt};
1112

1213
/// This returns true if the type `ty` is "trivial" for
1314
/// dropck-outlives -- that is, if it doesn't require any types to
@@ -93,6 +94,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
9394
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
9495
span: Span,
9596
) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
97+
match compute_dropck_outlives_with_errors(ocx, goal, span) {
98+
Ok(r) => Ok(r),
99+
Err(_) => Err(NoSolution),
100+
}
101+
}
102+
103+
pub fn compute_dropck_outlives_with_errors<'tcx, E>(
104+
ocx: &ObligationCtxt<'_, 'tcx, E>,
105+
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
106+
span: Span,
107+
) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
108+
where
109+
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
110+
{
96111
let tcx = ocx.infcx.tcx;
97112
let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
98113

@@ -149,11 +164,11 @@ pub fn compute_dropck_outlives_inner<'tcx>(
149164
dtorck_constraint_for_ty_inner(
150165
tcx,
151166
ocx.infcx.typing_env(param_env),
152-
DUMMY_SP,
167+
span,
153168
depth,
154169
ty,
155170
&mut constraints,
156-
)?;
171+
);
157172

158173
// "outlives" represent types/regions that may be touched
159174
// by a destructor.
@@ -173,11 +188,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
173188
// do not themselves define a destructor", more or less. We have
174189
// to push them onto the stack to be expanded.
175190
for ty in constraints.dtorck_types.drain(..) {
176-
let Normalized { value: ty, obligations } =
177-
ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
178-
ocx.register_obligations(obligations);
191+
let ty = if let Ok(Normalized { value: ty, obligations }) =
192+
ocx.infcx.at(&cause, param_env).query_normalize(ty)
193+
{
194+
ocx.register_obligations(obligations);
195+
196+
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
197+
ty
198+
} else {
199+
ocx.deeply_normalize(&cause, param_env, ty)?;
179200

180-
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
201+
let errors = ocx.select_where_possible();
202+
debug!("normalize errors: {ty} ~> {errors:#?}");
203+
return Err(errors);
204+
};
181205

182206
match ty.kind() {
183207
// All parameters live for the duration of the
@@ -213,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
213237
depth: usize,
214238
ty: Ty<'tcx>,
215239
constraints: &mut DropckConstraint<'tcx>,
216-
) -> Result<(), NoSolution> {
240+
) {
217241
if !tcx.recursion_limit().value_within_limit(depth) {
218242
constraints.overflows.push(ty);
219-
return Ok(());
243+
return;
220244
}
221245

222246
if trivial_dropck_outlives(tcx, ty) {
223-
return Ok(());
247+
return;
224248
}
225249

226250
match ty.kind() {
@@ -244,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
244268
// single-element containers, behave like their element
245269
rustc_data_structures::stack::ensure_sufficient_stack(|| {
246270
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
247-
})?;
271+
});
248272
}
249273

250274
ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
251275
for ty in tys.iter() {
252-
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
276+
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
253277
}
254-
Ok::<_, NoSolution>(())
255-
})?,
278+
}),
256279

257280
ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
258281
for ty in args.as_closure().upvar_tys() {
259-
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
282+
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
260283
}
261-
Ok::<_, NoSolution>(())
262-
})?,
284+
}),
263285

264286
ty::CoroutineClosure(_, args) => {
265287
rustc_data_structures::stack::ensure_sufficient_stack(|| {
@@ -271,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
271293
depth + 1,
272294
ty,
273295
constraints,
274-
)?;
296+
);
275297
}
276-
Ok::<_, NoSolution>(())
277-
})?
298+
})
278299
}
279300

280301
ty::Coroutine(_, args) => {
@@ -313,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
313334

314335
ty::Adt(def, args) => {
315336
let DropckConstraint { dtorck_types, outlives, overflows } =
316-
tcx.at(span).adt_dtorck_constraint(def.did())?;
337+
tcx.at(span).adt_dtorck_constraint(def.did());
317338
// FIXME: we can try to recursively `dtorck_constraint_on_ty`
318339
// there, but that needs some way to handle cycles.
319340
constraints
@@ -346,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
346367
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
347368
// By the time this code runs, all type variables ought to
348369
// be fully resolved.
349-
return Err(NoSolution);
370+
tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty));
350371
}
351372
}
352-
353-
Ok(())
354373
}

compiler/rustc_traits/src/dropck_outlives.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@ fn dropck_outlives<'tcx>(
3030
}
3131

3232
/// Calculates the dtorck constraint for a type.
33-
pub(crate) fn adt_dtorck_constraint(
34-
tcx: TyCtxt<'_>,
35-
def_id: DefId,
36-
) -> Result<&DropckConstraint<'_>, NoSolution> {
33+
pub(crate) fn adt_dtorck_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &DropckConstraint<'_> {
3734
let def = tcx.adt_def(def_id);
3835
let span = tcx.def_span(def_id);
3936
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
@@ -52,20 +49,20 @@ pub(crate) fn adt_dtorck_constraint(
5249
overflows: vec![],
5350
};
5451
debug!("dtorck_constraint: {:?} => {:?}", def, result);
55-
return Ok(tcx.arena.alloc(result));
52+
return tcx.arena.alloc(result);
5653
}
5754

5855
let mut result = DropckConstraint::empty();
5956
for field in def.all_fields() {
6057
let fty = tcx.type_of(field.did).instantiate_identity();
61-
dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?;
58+
dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result);
6259
}
6360
result.outlives.extend(tcx.destructor_constraints(def));
6461
dedup_dtorck_constraint(&mut result);
6562

6663
debug!("dtorck_constraint: {:?} => {:?}", def, result);
6764

68-
Ok(tcx.arena.alloc(result))
65+
tcx.arena.alloc(result)
6966
}
7067

7168
fn dedup_dtorck_constraint(c: &mut DropckConstraint<'_>) {

tests/crashes/103899.rs

Lines changed: 0 additions & 27 deletions
This file was deleted.

tests/crashes/105299.rs

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test that we don't ICE for a typeck error that only shows up in dropck
2+
// Version where the normalization error is an ambiguous trait implementation.
3+
// <[T] as ToOwned>::Owned is ambiguous on whether to use T: Clone or [T]::Clone.
4+
// Regression test for #105299
5+
6+
pub trait Foo: Clone {}
7+
8+
pub struct Bar<'a, T: Clone> {
9+
pub cow: std::borrow::Cow<'a, [T]>,
10+
11+
pub THIS_CAUSES_ICE: (),
12+
}
13+
14+
impl<T> Bar<'_, T>
15+
where
16+
T: Clone,
17+
[T]: Foo,
18+
{
19+
pub fn MOVES_SELF(self) {}
20+
//~^ ERROR type annotations needed
21+
}
22+
23+
pub fn main() {}

0 commit comments

Comments
 (0)