Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #66403

Merged
merged 21 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7e94cc3
Update E0210 to match RFC 2451
ohadravid Nov 8, 2019
2db744c
Improve coherence errors for wrong type order
ohadravid Nov 9, 2019
292ba98
fix an ICE in macro's diagnostic message
Nov 10, 2019
fe4b709
expand source_util macros with def-site context
euclio Nov 12, 2019
302cf6d
Tweak non-char/numeric in range pattern diagnostic
JohnTitor Nov 12, 2019
0cd111f
Doc: Fix link to Exten in Vec::set_len
elichai Nov 13, 2019
dcd91d5
parser: don't use `unreachable!()` in `fn unexpected`.
Centril Nov 13, 2019
b03afd5
Improve error message in make_tests
Munksgaard Nov 13, 2019
c154297
Fix broken links in Ipv4Addr::is_benchmarking docs
ogham Nov 13, 2019
030fa9a
Avoid using same code
JohnTitor Nov 13, 2019
8c6e297
compiletest: Obtain timestamps for common inputs only once
tmiasko Nov 11, 2019
1ac470f
compiletest: Avoid double negation in ignore condition
tmiasko Nov 13, 2019
79e2afc
Rollup merge of #66253 - ohadravid:improve-errors-after-re-rebalance-…
JohnTitor Nov 14, 2019
187e911
Rollup merge of #66264 - guanqun:fix-mbe-missing-close-delim, r=estebank
JohnTitor Nov 14, 2019
2acbd3d
Rollup merge of #66349 - euclio:def-site-builtins, r=petrochenkov
JohnTitor Nov 14, 2019
20c3562
Rollup merge of #66351 - JohnTitor:tweak-range-err-msg, r=Centril
JohnTitor Nov 14, 2019
28c0e40
Rollup merge of #66360 - elichai:2019-11-vec-link, r=dtolnay
JohnTitor Nov 14, 2019
8d05997
Rollup merge of #66361 - Centril:66357, r=pnkfelix
JohnTitor Nov 14, 2019
2d453b3
Rollup merge of #66363 - Munksgaard:patch-1, r=dtolnay
JohnTitor Nov 14, 2019
8bd8465
Rollup merge of #66369 - tmiasko:compiletest-stamp, r=Mark-Simulacrum
JohnTitor Nov 14, 2019
d145d1e
Rollup merge of #66372 - ogham:patch-2, r=jonas-schievink
JohnTitor Nov 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/liballoc/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ impl<T> Vec<T> {
///
/// [`truncate`]: #method.truncate
/// [`resize`]: #method.resize
/// [`extend`]: #method.extend-1
/// [`extend`]: ../../std/iter/trait.Extend.html#tymethod.extend
/// [`clear`]: #method.clear
///
/// # Safety
Expand Down
12 changes: 10 additions & 2 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(

pub enum OrphanCheckErr<'tcx> {
NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
UncoveredTy(Ty<'tcx>),
UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
}

/// Checks the coherence orphan rules. `impl_def_id` should be the
Expand Down Expand Up @@ -402,7 +402,15 @@ fn orphan_check_trait_ref<'tcx>(
return Ok(());
} else if let ty::Param(_) = input_ty.kind {
debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
return Err(OrphanCheckErr::UncoveredTy(input_ty))
let local_type = trait_ref
.input_types()
.flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
.filter(|ty| ty_is_non_local_constructor(tcx, ty, in_crate).is_none())
.next();

debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);

return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type))
}
if let Some(non_local_tys) = non_local_tys {
for input_ty in non_local_tys {
Expand Down
15 changes: 13 additions & 2 deletions src/librustc_parse/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1742,14 +1742,25 @@ impl<'a> Parser<'a> {
}

fn report_invalid_macro_expansion_item(&self) {
let has_close_delim = self.sess.source_map()
.span_to_snippet(self.prev_span)
.map(|s| s.ends_with(")") || s.ends_with("]"))
.unwrap_or(false);
let right_brace_span = if has_close_delim {
// it's safe to peel off one character only when it has the close delim
self.prev_span.with_lo(self.prev_span.hi() - BytePos(1))
} else {
self.sess.source_map().next_point(self.prev_span)
};

self.struct_span_err(
self.prev_span,
"macros that expand to items must be delimited with braces or followed by a semicolon",
).multipart_suggestion(
"change the delimiters to curly braces",
vec![
(self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")),
(self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()),
(self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), "{".to_string()),
(right_brace_span, '}'.to_string()),
],
Applicability::MaybeIncorrect,
).span_suggestion(
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_parse/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,9 @@ impl<'a> Parser<'a> {
crate fn unexpected<T>(&mut self) -> PResult<'a, T> {
match self.expect_one_of(&[], &[]) {
Err(e) => Err(e),
Ok(_) => unreachable!(),
// We can get `Ok(true)` from `recover_closing_delimiter`
// which is called in `expected_one_of_not_found`.
Ok(_) => FatalError.raise(),
}
}

Expand Down
90 changes: 61 additions & 29 deletions src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,37 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| ty.is_char()
|| ty.references_error()
};
let lhs_compat = numeric_or_char(lhs_ty);
let rhs_compat = numeric_or_char(rhs_ty);

if !lhs_compat || !rhs_compat {
let span = if !lhs_compat && !rhs_compat {
span
} else if !lhs_compat {
begin.span
} else {
end.span
};
let lhs_fail = !numeric_or_char(lhs_ty);
let rhs_fail = !numeric_or_char(rhs_ty);

let mut err = struct_span_err!(
self.tcx.sess,
span,
E0029,
"only char and numeric types are allowed in range patterns"
if lhs_fail || rhs_fail {
self.emit_err_pat_range(
span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty
);
err.span_label(span, "ranges require char or numeric types");
err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"In a match expression, only numbers and characters can be matched \
against a range. This is because the compiler checks that the range \
is non-empty at compile-time, and is unable to evaluate arbitrary \
comparison functions. If you want to capture values of an orderable \
type between two end-points, you can use a guard."
);
}
err.emit();
return None;
}

Expand All @@ -406,6 +382,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(common_type)
}

fn emit_err_pat_range(
&self,
span: Span,
begin_span: Span,
end_span: Span,
lhs_fail: bool,
rhs_fail: bool,
lhs_ty: Ty<'tcx>,
rhs_ty: Ty<'tcx>,
) {
let span = if lhs_fail && rhs_fail {
span
} else if lhs_fail {
begin_span
} else {
end_span
};

let mut err = struct_span_err!(
self.tcx.sess,
span,
E0029,
"only char and numeric types are allowed in range patterns"
);
let msg = |ty| {
format!("this is of type `{}` but it should be `char` or numeric", ty)
};
let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
err.span_label(first_span, &msg(first_ty));
if !second_ty.references_error() {
err.span_label(
second_span,
&format!("this is of type `{}`", second_ty)
);
}
};
if lhs_fail && rhs_fail {
err.span_label(begin_span, &msg(lhs_ty));
err.span_label(end_span, &msg(rhs_ty));
} else if lhs_fail {
one_side_err(begin_span, lhs_ty, end_span, rhs_ty);
} else {
one_side_err(end_span, rhs_ty, begin_span, lhs_ty);
}
if self.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"In a match expression, only numbers and characters can be matched \
against a range. This is because the compiler checks that the range \
is non-empty at compile-time, and is unable to evaluate arbitrary \
comparison functions. If you want to capture values of an orderable \
type between two end-points, you can use a guard."
);
}
err.emit();
}

fn check_pat_ident(
&self,
pat: &Pat,
Expand Down
64 changes: 46 additions & 18 deletions src/librustc_typeck/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,30 +77,58 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
err.emit();
return;
}
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => {
let mut sp = sp;
for param in &generics.params {
if param.name.ident().to_string() == param_ty.to_string() {
sp = param.span;
}
}
let mut err = struct_span_err!(
self.tcx.sess,
sp,
E0210,
"type parameter `{}` must be used as the type parameter for some local \
type (e.g., `MyStruct<{}>`)",
param_ty,
param_ty
);
err.span_label(sp, format!(
"type parameter `{}` must be used as the type parameter for some local \
type",
param_ty,
));
err.note("only traits defined in the current crate can be implemented for a \
type parameter");
err.emit();

match local_type {
Some(local_type) => {
struct_span_err!(
self.tcx.sess,
sp,
E0210,
"type parameter `{}` must be covered by another type \
when it appears before the first local type (`{}`)",
param_ty,
local_type
).span_label(sp, format!(
"type parameter `{}` must be covered by another type \
when it appears before the first local type (`{}`)",
param_ty,
local_type
)).note("implementing a foreign trait is only possible if at \
least one of the types for which is it implemented is local, \
and no uncovered type parameters appear before that first \
local type"
).note("in this case, 'before' refers to the following order: \
`impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
where `T0` is the first and `Tn` is the last"
).emit();
}
None => {
struct_span_err!(
self.tcx.sess,
sp,
E0210,
"type parameter `{}` must be used as the type parameter for some \
local type (e.g., `MyStruct<{}>`)",
param_ty,
param_ty
).span_label(sp, format!(
"type parameter `{}` must be used as the type parameter for some \
local type",
param_ty,
)).note("implementing a foreign trait is only possible if at \
least one of the types for which is it implemented is local"
).note("only traits defined in the current crate can be \
implemented for a type parameter"
).emit();
}
};
return;
}
}
Expand Down
23 changes: 17 additions & 6 deletions src/librustc_typeck/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2114,8 +2114,13 @@ E0210: r##"
This error indicates a violation of one of Rust's orphan rules for trait
implementations. The rule concerns the use of type parameters in an
implementation of a foreign trait (a trait defined in another crate), and
states that type parameters must be "covered" by a local type. To understand
what this means, it is perhaps easiest to consider a few examples.
states that type parameters must be "covered" by a local type.

When implementing a foreign trait for a foreign type,
the trait must have one or more type parameters.
A type local to your crate must appear before any use of any type parameters.

To understand what this means, it is perhaps easier to consider a few examples.

If `ForeignTrait` is a trait defined in some external crate `foo`, then the
following trait `impl` is an error:
Expand Down Expand Up @@ -2173,12 +2178,18 @@ impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }

where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
are types. One of the types `T0, ..., Tn` must be a local type (this is another
orphan rule, see the explanation for E0117). Let `i` be the smallest integer
such that `Ti` is a local type. Then no type parameter can appear in any of the
`Tj` for `j < i`.
orphan rule, see the explanation for E0117).

For information on the design of the orphan rules, see [RFC 1023].
Both of the following must be true:
1. At least one of the types `T0..=Tn` must be a local type.
Let `Ti` be the first such type.
2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti`
(excluding `Ti`).

For information on the design of the orphan rules,
see [RFC 2451] and [RFC 1023].

[RFC 2451]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html
[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
"##,

Expand Down
4 changes: 2 additions & 2 deletions src/libstd/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,8 @@ impl Ipv4Addr {
/// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
/// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
///
/// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
/// [errate 423]: https://www.rfc-editor.org/errata/eid423
/// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
/// [errata 423]: https://www.rfc-editor.org/errata/eid423
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
Expand Down
8 changes: 8 additions & 0 deletions src/libsyntax_ext/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rustc_data_structures::sync::Lrc;
/// line!(): expands to the current line number
pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
base::check_zero_tts(cx, sp, tts, "line!");

let topmost = cx.expansion_cause().unwrap_or(sp);
Expand All @@ -32,6 +33,7 @@ pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
/* column!(): expands to the current column number */
pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
base::check_zero_tts(cx, sp, tts, "column!");

let topmost = cx.expansion_cause().unwrap_or(sp);
Expand All @@ -45,6 +47,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
/// out if we wanted.
pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
base::check_zero_tts(cx, sp, tts, "file!");

let topmost = cx.expansion_cause().unwrap_or(sp);
Expand All @@ -54,12 +57,14 @@ pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)

pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
let s = pprust::tts_to_string(tts);
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
}

pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
base::check_zero_tts(cx, sp, tts, "module_path!");
let mod_path = &cx.current_expansion.module.mod_path;
let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
Expand All @@ -72,6 +77,7 @@ pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
/// unhygienically.
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'cx> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
Some(f) => f,
None => return DummyResult::any(sp),
Expand Down Expand Up @@ -125,6 +131,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
// include_str! : read the given file, insert it as a literal string expr
pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
Some(f) => f,
None => return DummyResult::any(sp)
Expand Down Expand Up @@ -156,6 +163,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)

pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
-> Box<dyn base::MacResult+'static> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
Some(f) => f,
None => return DummyResult::any(sp)
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/coherence/coherence-all-remote.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<T> for isize { }
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter

error: aborting due to previous error
Expand Down
7 changes: 4 additions & 3 deletions src/test/ui/coherence/coherence-bigint-param.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
--> $DIR/coherence-bigint-param.rs:8:6
|
LL | impl<T> Remote1<BigInt> for T { }
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last

error: aborting due to previous error

Expand Down
Loading