Skip to content

Commit 1e37e83

Browse files
committed
Auto merge of rust-lang#88414 - Aaron1011:guess-foreign-head-span, r=estebank
Don't use `guess_head_span` in `predicates_of` for foreign span Previously, the result of `predicates_of` for a foreign trait would depend on the *current* state of the corresponding source file in the foreign crate. This could lead to ICEs during incremental compilation, since the on-disk contents of the upstream source file could potentially change without the upstream crate being recompiled. Additionally, this ensure that that the metadata we produce for a crate only depends on its *compiled* upstream dependencies (e.g an rlib or rmeta file), *not* the current on-disk state of the upstream crate source files.
2 parents 56ea5e0 + c9157ef commit 1e37e83

File tree

9 files changed

+97
-15
lines changed

9 files changed

+97
-15
lines changed

compiler/rustc_span/src/source_map.rs

+11
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,17 @@ impl SourceMap {
567567
}
568568
}
569569

570+
/// Returns whether or not this span points into a file
571+
/// in the current crate. This may be `false` for spans
572+
/// produced by a macro expansion, or for spans associated
573+
/// with the definition of an item in a foreign crate
574+
pub fn is_local_span(&self, sp: Span) -> bool {
575+
let local_begin = self.lookup_byte_offset(sp.lo());
576+
let local_end = self.lookup_byte_offset(sp.hi());
577+
// This might be a weird span that covers multiple files
578+
local_begin.sf.src.is_some() && local_end.sf.src.is_some()
579+
}
580+
570581
/// Returns the source snippet as `String` corresponding to the given `Span`.
571582
pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
572583
self.span_to_source(sp, |src, start_index, end_index| {

compiler/rustc_typeck/src/collect.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -2002,7 +2002,16 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
20022002
// prove that the trait applies to the types that were
20032003
// used, and adding the predicate into this list ensures
20042004
// that this is done.
2005-
let span = tcx.sess.source_map().guess_head_span(tcx.def_span(def_id));
2005+
let mut span = tcx.def_span(def_id);
2006+
if tcx.sess.source_map().is_local_span(span) {
2007+
// `guess_head_span` reads the actual source file from
2008+
// disk to try to determine the 'head' snippet of the span.
2009+
// Don't do this for a span that comes from a file outside
2010+
// of our crate, since this would make our query output
2011+
// (and overall crate metadata) dependent on the
2012+
// *current* state of an external file.
2013+
span = tcx.sess.source_map().guess_head_span(span);
2014+
}
20062015
result.predicates =
20072016
tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
20082017
ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
include ../../run-make-fulldeps/tools.mk
2+
3+
# ignore-none no-std is not supported
4+
# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
5+
6+
# Ensure that modifying a crate on disk (without recompiling it)
7+
# does not cause ICEs in downstream crates.
8+
# Previously, we would call `SourceMap.guess_head_span` on a span
9+
# from an external crate, which would cause us to read an upstream
10+
# source file from disk during compilation of a downstream crate
11+
# See #86480 for more details
12+
13+
INCR=$(TMPDIR)/incr
14+
15+
all:
16+
cp first_crate.rs second_crate.rs $(TMPDIR)
17+
$(RUSTC) $(TMPDIR)/first_crate.rs -C incremental=$(INCR) --target $(TARGET) --crate-type lib
18+
$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --extern first-crate=$(TMPDIR) --crate-type lib
19+
rm $(TMPDIR)/first_crate.rs
20+
$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub trait OtherTrait {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
extern crate first_crate;
2+
use first_crate::OtherTrait;
3+
4+
#[cfg(not(second_run))]
5+
trait Foo: OtherTrait {}
6+
7+
#[cfg(second_run)]
8+
trait Bar: OtherTrait {}

src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr

+20-6
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
88
note: required by a bound in `Send`
99
--> $SRC_DIR/core/src/marker.rs:LL:COL
1010
|
11-
LL | pub unsafe auto trait Send {
12-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Send`
11+
LL | / pub unsafe auto trait Send {
12+
LL | | // empty.
13+
LL | | }
14+
| |_^ required by this bound in `Send`
1315
help: consider further restricting the associated type
1416
|
1517
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
@@ -25,8 +27,14 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
2527
note: required by a bound in `Iterator`
2628
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
2729
|
28-
LL | pub trait Iterator {
29-
| ^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator`
30+
LL | / pub trait Iterator {
31+
LL | | /// The type of the elements being iterated over.
32+
LL | | #[stable(feature = "rust1", since = "1.0.0")]
33+
LL | | type Item;
34+
... |
35+
LL | | }
36+
LL | | }
37+
| |_^ required by this bound in `Iterator`
3038
help: consider further restricting the associated type
3139
|
3240
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
@@ -42,8 +50,14 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
4250
note: required by a bound in `Sync`
4351
--> $SRC_DIR/core/src/marker.rs:LL:COL
4452
|
45-
LL | pub unsafe auto trait Sync {
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Sync`
53+
LL | / pub unsafe auto trait Sync {
54+
LL | | // FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
55+
LL | | // lands in beta, and it has been extended to check whether a closure is
56+
LL | | // anywhere in the requirement chain, extend it as such (#48534):
57+
... |
58+
LL | | // Empty
59+
LL | | }
60+
| |_^ required by this bound in `Sync`
4761
help: consider further restricting the associated type
4862
|
4963
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {

src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ LL | type A: Iterator<Item: Debug>;
88
note: required by a bound in `Debug`
99
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
1010
|
11-
LL | pub trait Debug {
12-
| ^^^^^^^^^^^^^^^ required by this bound in `Debug`
11+
LL | / pub trait Debug {
12+
LL | | /// Formats the value using the given formatter.
13+
LL | | ///
14+
LL | | /// # Examples
15+
... |
16+
LL | | fn fmt(&self, f: &mut Formatter<'_>) -> Result;
17+
LL | | }
18+
| |_^ required by this bound in `Debug`
1319
help: consider further restricting the associated type
1420
|
1521
LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug {
@@ -24,8 +30,14 @@ LL | pub trait Foo { type Out: Baz<Assoc: Default>; }
2430
note: required by a bound in `Default`
2531
--> $SRC_DIR/core/src/default.rs:LL:COL
2632
|
27-
LL | pub trait Default: Sized {
28-
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Default`
33+
LL | / pub trait Default: Sized {
34+
LL | | /// Returns the "default value" for a type.
35+
LL | | ///
36+
LL | | /// Default values are often some kind of initial value, identity value, or anything else that
37+
... |
38+
LL | | fn default() -> Self;
39+
LL | | }
40+
| |_^ required by this bound in `Default`
2941
help: consider further restricting the associated type
3042
|
3143
LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; }

src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,10 @@ LL | type A: Iterator<Item: Copy>;
142142
note: required by a bound in `Copy`
143143
--> $SRC_DIR/core/src/marker.rs:LL:COL
144144
|
145-
LL | pub trait Copy: Clone {
146-
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Copy`
145+
LL | / pub trait Copy: Clone {
146+
LL | | // Empty.
147+
LL | | }
148+
| |_^ required by this bound in `Copy`
147149
help: consider further restricting the associated type
148150
|
149151
LL | trait _Tr3 where <<Self as _Tr3>::A as Iterator>::Item: Copy {

src/test/ui/traits/issue-85735.stderr

+6-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ LL | T: FnMut(&'a ()),
88
note: required by a bound in `FnMut`
99
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
1010
|
11-
LL | pub trait FnMut<Args>: FnOnce<Args> {
12-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `FnMut`
11+
LL | / pub trait FnMut<Args>: FnOnce<Args> {
12+
LL | | /// Performs the call operation.
13+
LL | | #[unstable(feature = "fn_traits", issue = "29625")]
14+
LL | | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
15+
LL | | }
16+
| |_^ required by this bound in `FnMut`
1317

1418
error: aborting due to previous error
1519

0 commit comments

Comments
 (0)