Skip to content

Commit 3dbc9ed

Browse files
Properly bubble up ambiguity in normalize query
1 parent 542febd commit 3dbc9ed

File tree

6 files changed

+62
-12
lines changed

6 files changed

+62
-12
lines changed

compiler/rustc_middle/src/traits/query.rs

+27
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,33 @@ impl<'tcx> From<TypeError<'tcx>> for NoSolution {
109109
}
110110
}
111111

112+
#[derive(Copy, Clone, Debug, HashStable)]
113+
pub enum NoSolutionOrAmbiguous {
114+
NoSolution,
115+
Ambiguous,
116+
}
117+
118+
impl NoSolutionOrAmbiguous {
119+
pub fn expect_unambiguous(self) -> NoSolution {
120+
match self {
121+
NoSolutionOrAmbiguous::NoSolution => NoSolution,
122+
NoSolutionOrAmbiguous::Ambiguous => bug!("unexpected ambiguity"),
123+
}
124+
}
125+
}
126+
127+
impl From<NoSolution> for NoSolutionOrAmbiguous {
128+
fn from(_: NoSolution) -> NoSolutionOrAmbiguous {
129+
NoSolutionOrAmbiguous::NoSolution
130+
}
131+
}
132+
133+
impl<'tcx> From<TypeError<'tcx>> for NoSolutionOrAmbiguous {
134+
fn from(_: TypeError<'tcx>) -> NoSolutionOrAmbiguous {
135+
NoSolutionOrAmbiguous::NoSolution
136+
}
137+
}
138+
112139
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
113140
pub struct DropckOutlivesResult<'tcx> {
114141
pub kinds: Vec<GenericArg<'tcx>>,

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
1717

1818
use std::ops::ControlFlow;
1919

20-
use super::NoSolution;
20+
use super::NoSolutionOrAmbiguous;
2121

2222
pub use rustc_middle::traits::query::NormalizationResult;
2323

2424
pub trait AtExt<'tcx> {
25-
fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
25+
fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolutionOrAmbiguous>
2626
where
2727
T: TypeFoldable<'tcx>;
2828
}
@@ -41,7 +41,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
4141
/// normalizing, but for now should be used only when we actually
4242
/// know that normalization will succeed, since error reporting
4343
/// and other details are still "under development".
44-
fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
44+
fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolutionOrAmbiguous>
4545
where
4646
T: TypeFoldable<'tcx>,
4747
{
@@ -96,7 +96,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
9696
std::any::type_name::<T>(),
9797
normalizer.obligations,
9898
);
99-
result.map(|value| Normalized { value, obligations: normalizer.obligations })
99+
Ok(Normalized { value: result?, obligations: normalizer.obligations })
100100
}
101101
}
102102

@@ -163,7 +163,7 @@ struct QueryNormalizer<'cx, 'tcx> {
163163
}
164164

165165
impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
166-
type Error = NoSolution;
166+
type Error = NoSolutionOrAmbiguous;
167167

168168
fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
169169
self.infcx.tcx
@@ -253,7 +253,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
253253
let result = tcx.normalize_projection_ty(c_data)?;
254254
// We don't expect ambiguity.
255255
if result.is_ambiguous() {
256-
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
256+
return Err(NoSolutionOrAmbiguous::Ambiguous);
257257
}
258258
let InferOk { value: result, obligations } =
259259
self.infcx.instantiate_query_response_and_region_obligations(
@@ -296,7 +296,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
296296
let result = tcx.normalize_projection_ty(c_data)?;
297297
// We don't expect ambiguity.
298298
if result.is_ambiguous() {
299-
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
299+
return Err(NoSolutionOrAmbiguous::Ambiguous);
300300
}
301301
let InferOk { value: result, obligations } =
302302
self.infcx.instantiate_query_response_and_region_obligations(

compiler/rustc_traits/src/dropck_outlives.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ fn dropck_outlives<'tcx>(
131131

132132
// We don't actually expect to fail to normalize.
133133
// That implies a WF error somewhere else.
134-
Err(NoSolution) => {
135-
return Err(NoSolution);
134+
Err(err) => {
135+
return Err(err.expect_unambiguous());
136136
}
137137
}
138138
}

compiler/rustc_traits/src/normalize_erasing_regions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
4848
debug_assert!(!erased.needs_infer(), "{:?}", erased);
4949
Ok(erased)
5050
}
51-
Err(NoSolution) => Err(NoSolution),
51+
Err(err) => Err(err.expect_unambiguous()),
5252
}
5353
}
5454

compiler/rustc_traits/src/type_op.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,10 @@ where
218218
T: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx>,
219219
{
220220
let (param_env, Normalize { value }) = key.into_parts();
221-
let Normalized { value, obligations } =
222-
infcx.at(&ObligationCause::dummy(), param_env).normalize(value)?;
221+
let Normalized { value, obligations } = infcx
222+
.at(&ObligationCause::dummy(), param_env)
223+
.normalize(value)
224+
.map_err(|err| err.expect_unambiguous())?;
223225
fulfill_cx.register_predicate_obligations(infcx, obligations);
224226
Ok(value)
225227
}

src/test/rustdoc/issue-102835.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -Znormalize-docs
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
trait Allocator {
6+
type Buffer;
7+
}
8+
9+
struct DefaultAllocator;
10+
11+
impl<T> Allocator for DefaultAllocator {
12+
type Buffer = ();
13+
}
14+
15+
type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
16+
17+
fn foo() -> A {
18+
|_| ()
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)