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 5 pull requests #91080

Merged
merged 19 commits into from
Nov 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d64aea6
Fix `non-constant value` ICE (#90878)
Noratrieb Nov 15, 2021
483cff7
Add SourceMap::indentation_before.
m-ou-se Nov 4, 2021
453e242
Improve suggestion for unit Option/Result at the end of a block.
m-ou-se Nov 4, 2021
b331b66
Improve compatible enum variant suggestions.
m-ou-se Nov 4, 2021
4877756
Update tests.
m-ou-se Nov 4, 2021
5a25751
Add new tests for compatible variant diagnostics.
m-ou-se Nov 4, 2021
09e4a75
Use span_suggestions instead of multipart_suggestions.
m-ou-se Nov 4, 2021
b66fb64
Update test output.
m-ou-se Nov 16, 2021
7c7f58d
Fix case where ICE #90878 was still triggered by a leading newline
Noratrieb Nov 16, 2021
bf10c88
Make scrollbar in the sidebar always visible for visual consistency
GuillaumeGomez Nov 17, 2021
495d8ed
tidy-ignore-leading-newlines
Noratrieb Nov 17, 2021
96c37c8
Add a test with a leading newline for ICE #90878
Noratrieb Nov 17, 2021
f6392a1
Print output ty for opaque future ty
compiler-errors Nov 17, 2021
33ab512
Clarify error messages caused by re-exporting `pub(crate)` visibility…
ken-matsui Nov 5, 2021
7354bb3
Rollup merge of #90575 - m-ou-se:compatible-variant-improvements, r=e…
matthiaskrgr Nov 20, 2021
81f3ae8
Rollup merge of #90628 - ken-matsui:clarify-error-messages-caused-by-…
matthiaskrgr Nov 20, 2021
7993571
Rollup merge of #90930 - Nilstrieb:fix-non-const-value-ice, r=estebank
matthiaskrgr Nov 20, 2021
59c9c66
Rollup merge of #90983 - GuillaumeGomez:sidebar-scrollbar, r=jsha
matthiaskrgr Nov 20, 2021
3379721
Rollup merge of #91021 - compiler-errors:print_future_output, r=estebank
matthiaskrgr Nov 20, 2021
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
66 changes: 55 additions & 11 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,30 +649,74 @@ pub trait PrettyPrinter<'tcx>:

let mut first = true;
let mut is_sized = false;
let mut is_future = false;
let mut future_output_ty = None;

p!("impl");
for (predicate, _) in bounds {
let predicate = predicate.subst(self.tcx(), substs);
let bound_predicate = predicate.kind();
if let ty::PredicateKind::Trait(pred) = bound_predicate.skip_binder() {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
is_sized = true;
continue;

match bound_predicate.skip_binder() {
ty::PredicateKind::Projection(projection_predicate) => {
let Some(future_trait) = self.tcx().lang_items().future_trait() else { continue };
let future_output_def_id =
self.tcx().associated_item_def_ids(future_trait)[0];

if projection_predicate.projection_ty.item_def_id
== future_output_def_id
{
// We don't account for multiple `Future::Output = Ty` contraints.
is_future = true;
future_output_ty = Some(projection_predicate.ty);
}
}
ty::PredicateKind::Trait(pred) => {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait()
{
is_sized = true;
continue;
}

p!(
write("{}", if first { " " } else { "+" }),
print(trait_ref.print_only_trait_path())
);
first = false;
if Some(trait_ref.def_id())
== self.tcx().lang_items().future_trait()
{
is_future = true;
continue;
}

p!(
write("{}", if first { " " } else { "+" }),
print(trait_ref.print_only_trait_path())
);

first = false;
}
_ => {}
}
}

if is_future {
p!(write("{}Future", if first { " " } else { "+" }));
first = false;

if let Some(future_output_ty) = future_output_ty {
// Don't print projection types, which we (unfortunately) see often
// in the error outputs involving async blocks.
if !matches!(future_output_ty.kind(), ty::Projection(_)) {
p!("<Output = ", print(future_output_ty), ">");
}
}
}

if !is_sized {
p!(write("{}?Sized", if first { " " } else { "+" }));
} else if first {
p!(" Sized");
}

Ok(self)
});
}
Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,12 +450,24 @@ impl<'a> Resolver<'a> {
// let foo =...
// ^^^ given this Span
// ------- get this Span to have an applicable suggestion

// edit:
// only do this if the const and usage of the non-constant value are on the same line
// the further the two are apart, the higher the chance of the suggestion being wrong
// also make sure that the pos for the suggestion is not 0 (ICE #90878)

let sp =
self.session.source_map().span_extend_to_prev_str(ident.span, current, true);
if sp.lo().0 == 0 {

let pos_for_suggestion = sp.lo().0.saturating_sub(current.len() as u32);

if sp.lo().0 == 0
|| pos_for_suggestion == 0
|| self.session.source_map().is_multiline(sp)
{
err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
} else {
let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32));
let sp = sp.with_lo(BytePos(pos_for_suggestion));
err.span_suggestion(
sp,
&format!("consider using `{}` instead of `{}`", sugg, current),
Expand Down
50 changes: 33 additions & 17 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,11 +1180,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> {

let mut reexport_error = None;
let mut any_successful_reexport = false;
let mut crate_private_reexport = false;
self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
let vis = import.vis.get();
if !binding.vis.is_at_least(vis, &*this) {
reexport_error = Some((ns, binding));
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
if binding_def_id.is_top_level_module() {
crate_private_reexport = true;
}
}
} else {
any_successful_reexport = true;
}
Expand All @@ -1207,24 +1213,34 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
import.span,
&msg,
);
} else if ns == TypeNS {
struct_span_err!(
self.r.session,
import.span,
E0365,
"`{}` is private, and cannot be re-exported",
ident
)
.span_label(import.span, format!("re-export of private `{}`", ident))
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
let msg = format!("`{}` is private, and cannot be re-exported", ident);
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident,);
struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
.span_note(import.span, &note_msg)
.emit();
let error_msg = if crate_private_reexport {
format!(
"`{}` is only public within the crate, and cannot be re-exported outside",
ident
)
} else {
format!("`{}` is private, and cannot be re-exported", ident)
};

if ns == TypeNS {
let label_msg = if crate_private_reexport {
format!("re-export of crate public `{}`", ident)
} else {
format!("re-export of private `{}`", ident)
};

struct_span_err!(self.r.session, import.span, E0365, "{}", error_msg)
.span_label(import.span, label_msg)
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident);
struct_span_err!(self.r.session, import.span, E0364, "{}", error_msg)
.span_note(import.span, &note_msg)
.emit();
}
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1935,6 +1935,7 @@ pub struct Loc {
#[derive(Debug)]
pub struct SourceFileAndLine {
pub sf: Lrc<SourceFile>,
/// Index of line, starting from 0.
pub line: usize,
}
#[derive(Debug)]
Expand Down
19 changes: 12 additions & 7 deletions compiler/rustc_span/src/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,14 +593,19 @@ impl SourceMap {
}

pub fn span_to_margin(&self, sp: Span) -> Option<usize> {
match self.span_to_prev_source(sp) {
Err(_) => None,
Ok(source) => {
let last_line = source.rsplit_once('\n').unwrap_or(("", &source)).1;
Some(self.indentation_before(sp)?.len())
}

Some(last_line.len() - last_line.trim_start().len())
}
}
pub fn indentation_before(&self, sp: Span) -> Option<String> {
self.span_to_source(sp, |src, start_index, _| {
let before = &src[..start_index];
let last_line = before.rsplit_once('\n').map_or(before, |(_, last)| last);
Ok(last_line
.split_once(|c: char| !c.is_whitespace())
.map_or(last_line, |(indent, _)| indent)
.to_string())
})
.ok()
}

/// Returns the source snippet as `String` before the given `Span`.
Expand Down
83 changes: 70 additions & 13 deletions compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}

let mut compatible_variants = expected_adt
// If the expression is of type () and it's the return expression of a block,
// we suggest adding a separate return expression instead.
// (To avoid things like suggesting `Ok(while .. { .. })`.)
if expr_ty.is_unit() {
if let Some(hir::Node::Block(&hir::Block {
span: block_span, expr: Some(e), ..
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
{
if e.hir_id == expr.hir_id {
if let Some(span) = expr.span.find_ancestor_inside(block_span) {
let return_suggestions =
if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) {
vec!["Ok(())".to_string()]
} else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did)
{
vec!["None".to_string(), "Some(())".to_string()]
} else {
return;
};
if let Some(indent) =
self.tcx.sess.source_map().indentation_before(span.shrink_to_lo())
{
// Add a semicolon, except after `}`.
let semicolon =
match self.tcx.sess.source_map().span_to_snippet(span) {
Ok(s) if s.ends_with('}') => "",
_ => ";",
};
err.span_suggestions(
span.shrink_to_hi(),
"try adding an expression at the end of the block",
return_suggestions
.into_iter()
.map(|r| format!("{}\n{}{}", semicolon, indent, r)),
Applicability::MaybeIncorrect,
);
}
return;
}
}
}
}

let compatible_variants: Vec<String> = expected_adt
.variants
.iter()
.filter(|variant| variant.fields.len() == 1)
Expand All @@ -220,19 +263,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None
}
})
.peekable();
.collect();

if compatible_variants.peek().is_some() {
if let Ok(expr_text) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
let suggestions = compatible_variants.map(|v| format!("{}({})", v, expr_text));
let msg = "try using a variant of the expected enum";
err.span_suggestions(
expr.span,
msg,
suggestions,
Applicability::MaybeIncorrect,
);
}
if let [variant] = &compatible_variants[..] {
// Just a single matching variant.
err.multipart_suggestion(
&format!("try wrapping the expression in `{}`", variant),
vec![
(expr.span.shrink_to_lo(), format!("{}(", variant)),
(expr.span.shrink_to_hi(), ")".to_string()),
],
Applicability::MaybeIncorrect,
);
} else if compatible_variants.len() > 1 {
// More than one matching variant.
err.multipart_suggestions(
&format!(
"try wrapping the expression in a variant of `{}`",
self.tcx.def_path_str(expected_adt.did)
),
compatible_variants.into_iter().map(|variant| {
vec![
(expr.span.shrink_to_lo(), format!("{}(", variant)),
(expr.span.shrink_to_hi(), ")".to_string()),
]
}),
Applicability::MaybeIncorrect,
);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ nav.sub {
left: 0;
top: 0;
bottom: 0;
overflow: auto;
overflow-y: scroll;
}

/* Improve the scrollbar display on firefox */
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/html/static/css/themes/ayu.css
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ pre, .rustdoc.source .example-wrap {

/* Improve the scrollbar display on firefox */
* {
scrollbar-color: #5c6773 transparent;
scrollbar-color: #5c6773 #24292f;
}

.sidebar {
scrollbar-color: #5c6773 transparent;
scrollbar-color: #5c6773 #24292f;
}

/* Improve the scrollbar display on webkit-based browsers */
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/static/css/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pre, .rustdoc.source .example-wrap {
scrollbar-color: rgb(64, 65, 67) #717171;
}
.sidebar {
scrollbar-color: rgba(32,34,37,.6) transparent;
scrollbar-color: rgba(32,34,37,.6) #5a5a5a;
}

/* Improve the scrollbar display on webkit-based browsers */
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/async-await/async-fn-nonsend.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
LL | assert_send(local_dropped_before_await());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
|
= help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:24:5
|
Expand All @@ -27,7 +27,7 @@ error: future cannot be sent between threads safely
LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
|
= help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
note: future is not `Send` as this value is used across an await
--> $DIR/async-fn-nonsend.rs:33:20
|
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/dont-suggest-missing-await.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ note: while checking the return type of the `async fn`
LL | async fn make_u32() -> u32 {
| ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future`
found opaque type `impl Future<Output = u32>`
help: consider `await`ing on the `Future`
|
LL | take_u32(x.await)
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/async-await/generator-desc.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ note: while checking the return type of the `async fn`
|
LL | async fn two() {}
| ^ checked the `Output` of this `async fn`, found opaque type
= note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>)
found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>)
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types

Expand Down
Loading