Auto merge of #98335 - JohnTitor:rollup-j2zudxv, r=JohnTitor
Rollup of 11 pull requests Successful merges: - #94033 (Improve docs for `is_running` to explain use case) - #97269 (adjust transmute const stabilization version) - #97805 (Add proper tracing spans to rustc_trait_selection::traits::error_reporting) - #98022 (Fix erroneous span for borrowck error) - #98124 (Improve loading of crates.js and sidebar-items.js) - #98278 (Some token stream cleanups) - #98306 (`try_fold_unevaluated` for infallible folders) - #98313 (Remove lies in comments.) - #98323 (⬆️ rust-analyzer) - #98329 (Avoid an ICE and instead let the compiler report a useful error) - #98330 (update ioslice docs to use shared slices) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
72fd41a8b4
32 changed files with 359 additions and 334 deletions
|
@ -25,7 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use std::{fmt, iter, mem};
|
use std::{fmt, iter};
|
||||||
|
|
||||||
/// When the main Rust parser encounters a syntax-extension invocation, it
|
/// When the main Rust parser encounters a syntax-extension invocation, it
|
||||||
/// parses the arguments to the invocation as a token tree. This is a very
|
/// parses the arguments to the invocation as a token tree. This is a very
|
||||||
|
@ -399,45 +399,6 @@ impl TokenStream {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
|
|
||||||
match streams.len() {
|
|
||||||
0 => TokenStream::default(),
|
|
||||||
1 => streams.pop().unwrap(),
|
|
||||||
_ => {
|
|
||||||
// We are going to extend the first stream in `streams` with
|
|
||||||
// the elements from the subsequent streams. This requires
|
|
||||||
// using `make_mut()` on the first stream, and in practice this
|
|
||||||
// doesn't cause cloning 99.9% of the time.
|
|
||||||
//
|
|
||||||
// One very common use case is when `streams` has two elements,
|
|
||||||
// where the first stream has any number of elements within
|
|
||||||
// (often 1, but sometimes many more) and the second stream has
|
|
||||||
// a single element within.
|
|
||||||
|
|
||||||
// Determine how much the first stream will be extended.
|
|
||||||
// Needed to avoid quadratic blow up from on-the-fly
|
|
||||||
// reallocations (#57735).
|
|
||||||
let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
|
|
||||||
|
|
||||||
// Get the first stream. If it's `None`, create an empty
|
|
||||||
// stream.
|
|
||||||
let mut iter = streams.drain(..);
|
|
||||||
let mut first_stream_lrc = iter.next().unwrap().0;
|
|
||||||
|
|
||||||
// Append the elements to the first stream, after reserving
|
|
||||||
// space for them.
|
|
||||||
let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc);
|
|
||||||
first_vec_mut.reserve(num_appends);
|
|
||||||
for stream in iter {
|
|
||||||
first_vec_mut.extend(stream.0.iter().cloned());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the final `TokenStream`.
|
|
||||||
TokenStream(first_stream_lrc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trees(&self) -> CursorRef<'_> {
|
pub fn trees(&self) -> CursorRef<'_> {
|
||||||
CursorRef::new(self)
|
CursorRef::new(self)
|
||||||
}
|
}
|
||||||
|
@ -562,50 +523,65 @@ impl TokenStreamBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
|
pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
|
||||||
let mut stream = stream.into();
|
self.0.push(stream.into());
|
||||||
|
|
||||||
// If `self` is not empty and the last tree within the last stream is a
|
|
||||||
// token tree marked with `Joint`...
|
|
||||||
if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut()
|
|
||||||
&& let Some((TokenTree::Token(last_token), Spacing::Joint)) = last_stream_lrc.last()
|
|
||||||
// ...and `stream` is not empty and the first tree within it is
|
|
||||||
// a token tree...
|
|
||||||
&& let TokenStream(ref mut stream_lrc) = stream
|
|
||||||
&& let Some((TokenTree::Token(token), spacing)) = stream_lrc.first()
|
|
||||||
// ...and the two tokens can be glued together...
|
|
||||||
&& let Some(glued_tok) = last_token.glue(&token)
|
|
||||||
{
|
|
||||||
// ...then do so, by overwriting the last token
|
|
||||||
// tree in `self` and removing the first token tree
|
|
||||||
// from `stream`. This requires using `make_mut()`
|
|
||||||
// on the last stream in `self` and on `stream`,
|
|
||||||
// and in practice this doesn't cause cloning 99.9%
|
|
||||||
// of the time.
|
|
||||||
|
|
||||||
// Overwrite the last token tree with the merged
|
|
||||||
// token.
|
|
||||||
let last_vec_mut = Lrc::make_mut(last_stream_lrc);
|
|
||||||
*last_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
|
|
||||||
|
|
||||||
// Remove the first token tree from `stream`. (This
|
|
||||||
// is almost always the only tree in `stream`.)
|
|
||||||
let stream_vec_mut = Lrc::make_mut(stream_lrc);
|
|
||||||
stream_vec_mut.remove(0);
|
|
||||||
|
|
||||||
// Don't push `stream` if it's empty -- that could
|
|
||||||
// block subsequent token gluing, by getting
|
|
||||||
// between two token trees that should be glued
|
|
||||||
// together.
|
|
||||||
if !stream.is_empty() {
|
|
||||||
self.0.push(stream);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.0.push(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> TokenStream {
|
pub fn build(self) -> TokenStream {
|
||||||
TokenStream::from_streams(self.0)
|
let mut streams = self.0;
|
||||||
|
match streams.len() {
|
||||||
|
0 => TokenStream::default(),
|
||||||
|
1 => streams.pop().unwrap(),
|
||||||
|
_ => {
|
||||||
|
// We will extend the first stream in `streams` with the
|
||||||
|
// elements from the subsequent streams. This requires using
|
||||||
|
// `make_mut()` on the first stream, and in practice this
|
||||||
|
// doesn't cause cloning 99.9% of the time.
|
||||||
|
//
|
||||||
|
// One very common use case is when `streams` has two elements,
|
||||||
|
// where the first stream has any number of elements within
|
||||||
|
// (often 1, but sometimes many more) and the second stream has
|
||||||
|
// a single element within.
|
||||||
|
|
||||||
|
// Determine how much the first stream will be extended.
|
||||||
|
// Needed to avoid quadratic blow up from on-the-fly
|
||||||
|
// reallocations (#57735).
|
||||||
|
let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
|
||||||
|
|
||||||
|
// Get the first stream, which will become the result stream.
|
||||||
|
// If it's `None`, create an empty stream.
|
||||||
|
let mut iter = streams.drain(..);
|
||||||
|
let mut res_stream_lrc = iter.next().unwrap().0;
|
||||||
|
|
||||||
|
// Append the subsequent elements to the result stream, after
|
||||||
|
// reserving space for them.
|
||||||
|
let res_vec_mut = Lrc::make_mut(&mut res_stream_lrc);
|
||||||
|
res_vec_mut.reserve(num_appends);
|
||||||
|
for stream in iter {
|
||||||
|
let stream_iter = stream.0.iter().cloned();
|
||||||
|
|
||||||
|
// If (a) `res_mut_vec` is not empty and the last tree
|
||||||
|
// within it is a token tree marked with `Joint`, and (b)
|
||||||
|
// `stream` is not empty and the first tree within it is a
|
||||||
|
// token tree, and (c) the two tokens can be glued
|
||||||
|
// together...
|
||||||
|
if let Some((TokenTree::Token(last_tok), Spacing::Joint)) = res_vec_mut.last()
|
||||||
|
&& let Some((TokenTree::Token(tok), spacing)) = stream.0.first()
|
||||||
|
&& let Some(glued_tok) = last_tok.glue(&tok)
|
||||||
|
{
|
||||||
|
// ...then overwrite the last token tree in
|
||||||
|
// `res_vec_mut` with the glued token, and skip the
|
||||||
|
// first token tree from `stream`.
|
||||||
|
*res_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
|
||||||
|
res_vec_mut.extend(stream_iter.skip(1));
|
||||||
|
} else {
|
||||||
|
// Append all of `stream`.
|
||||||
|
res_vec_mut.extend(stream_iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenStream(res_stream_lrc)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,20 +655,6 @@ impl Cursor {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index(&self) -> usize {
|
|
||||||
self.index
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append(&mut self, new_stream: TokenStream) {
|
|
||||||
if new_stream.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let index = self.index;
|
|
||||||
let stream = mem::take(&mut self.stream);
|
|
||||||
*self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees();
|
|
||||||
self.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
|
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
|
||||||
self.stream.0[self.index..].get(n).map(|(tree, _)| tree)
|
self.stream.0[self.index..].get(n).map(|(tree, _)| tree)
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,12 +357,20 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
.add_element(live_region_vid, location);
|
.add_element(live_region_vid, location);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// HACK(compiler-errors): Constants that are gathered into Body.required_consts
|
||||||
|
// have their locations erased...
|
||||||
|
let locations = if location != Location::START {
|
||||||
|
location.to_locations()
|
||||||
|
} else {
|
||||||
|
Locations::All(constant.span)
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(annotation_index) = constant.user_ty {
|
if let Some(annotation_index) = constant.user_ty {
|
||||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||||
constant.literal.ty(),
|
constant.literal.ty(),
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||||
location.to_locations(),
|
locations,
|
||||||
ConstraintCategory::Boring,
|
ConstraintCategory::Boring,
|
||||||
) {
|
) {
|
||||||
let annotation = &self.cx.user_type_annotations[annotation_index];
|
let annotation = &self.cx.user_type_annotations[annotation_index];
|
||||||
|
@ -390,12 +398,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
promoted: &Body<'tcx>,
|
promoted: &Body<'tcx>,
|
||||||
ty,
|
ty,
|
||||||
san_ty| {
|
san_ty| {
|
||||||
if let Err(terr) = verifier.cx.eq_types(
|
if let Err(terr) =
|
||||||
ty,
|
verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring)
|
||||||
san_ty,
|
{
|
||||||
location.to_locations(),
|
|
||||||
ConstraintCategory::Boring,
|
|
||||||
) {
|
|
||||||
span_mirbug!(
|
span_mirbug!(
|
||||||
verifier,
|
verifier,
|
||||||
promoted,
|
promoted,
|
||||||
|
@ -416,7 +421,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Err(terr) = self.cx.fully_perform_op(
|
if let Err(terr) = self.cx.fully_perform_op(
|
||||||
location.to_locations(),
|
locations,
|
||||||
ConstraintCategory::Boring,
|
ConstraintCategory::Boring,
|
||||||
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
||||||
constant.literal.ty(),
|
constant.literal.ty(),
|
||||||
|
@ -435,7 +440,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
||||||
let unnormalized_ty = tcx.type_of(static_def_id);
|
let unnormalized_ty = tcx.type_of(static_def_id);
|
||||||
let locations = location.to_locations();
|
|
||||||
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
|
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
|
||||||
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
|
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
|
||||||
|
|
||||||
|
@ -454,7 +458,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
self.cx.normalize_and_prove_instantiated_predicates(
|
self.cx.normalize_and_prove_instantiated_predicates(
|
||||||
def_id,
|
def_id,
|
||||||
instantiated_predicates,
|
instantiated_predicates,
|
||||||
location.to_locations(),
|
locations,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,6 +329,7 @@ impl Ident {
|
||||||
sess.symbol_gallery.insert(sym, span);
|
sess.symbol_gallery.insert(sym, span);
|
||||||
Ident { sym, is_raw, span }
|
Ident { sym, is_raw, span }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dollar_crate(span: Span) -> Ident {
|
fn dollar_crate(span: Span) -> Ident {
|
||||||
// `$crate` is accepted as an ident only if it comes from the compiler.
|
// `$crate` is accepted as an ident only if it comes from the compiler.
|
||||||
Ident { sym: kw::DollarCrate, is_raw: false, span }
|
Ident { sym: kw::DollarCrate, is_raw: false, span }
|
||||||
|
@ -403,6 +404,7 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||||
fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
|
fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
|
||||||
stream.is_empty()
|
stream.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_str(&mut self, src: &str) -> Self::TokenStream {
|
fn from_str(&mut self, src: &str) -> Self::TokenStream {
|
||||||
parse_stream_from_source_str(
|
parse_stream_from_source_str(
|
||||||
FileName::proc_macro_source_code(src),
|
FileName::proc_macro_source_code(src),
|
||||||
|
@ -411,9 +413,11 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||||
Some(self.call_site),
|
Some(self.call_site),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string(&mut self, stream: &Self::TokenStream) -> String {
|
fn to_string(&mut self, stream: &Self::TokenStream) -> String {
|
||||||
pprust::tts_to_string(stream)
|
pprust::tts_to_string(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
|
fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
|
||||||
// Parse the expression from our tokenstream.
|
// Parse the expression from our tokenstream.
|
||||||
let expr: PResult<'_, _> = try {
|
let expr: PResult<'_, _> = try {
|
||||||
|
@ -464,12 +468,14 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_token_tree(
|
fn from_token_tree(
|
||||||
&mut self,
|
&mut self,
|
||||||
tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
|
tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
|
||||||
) -> Self::TokenStream {
|
) -> Self::TokenStream {
|
||||||
tree.to_internal()
|
tree.to_internal()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn concat_trees(
|
fn concat_trees(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: Option<Self::TokenStream>,
|
base: Option<Self::TokenStream>,
|
||||||
|
@ -484,6 +490,7 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||||
}
|
}
|
||||||
builder.build()
|
builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn concat_streams(
|
fn concat_streams(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: Option<Self::TokenStream>,
|
base: Option<Self::TokenStream>,
|
||||||
|
@ -498,6 +505,7 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||||
}
|
}
|
||||||
builder.build()
|
builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_trees(
|
fn into_trees(
|
||||||
&mut self,
|
&mut self,
|
||||||
stream: Self::TokenStream,
|
stream: Self::TokenStream,
|
||||||
|
@ -522,11 +530,11 @@ impl server::TokenStream for Rustc<'_, '_> {
|
||||||
// FIXME: It needs to be removed, but there are some
|
// FIXME: It needs to be removed, but there are some
|
||||||
// compatibility issues (see #73345).
|
// compatibility issues (see #73345).
|
||||||
if group.flatten {
|
if group.flatten {
|
||||||
cursor.append(group.stream);
|
tts.append(&mut self.into_trees(group.stream));
|
||||||
continue;
|
} else {
|
||||||
}
|
|
||||||
tts.push(TokenTree::Group(group));
|
tts.push(TokenTree::Group(group));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Some(tt) => tts.push(tt),
|
Some(tt) => tts.push(tt),
|
||||||
None => return tts,
|
None => return tts,
|
||||||
}
|
}
|
||||||
|
@ -543,21 +551,27 @@ impl server::Group for Rustc<'_, '_> {
|
||||||
flatten: false,
|
flatten: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delimiter(&mut self, group: &Self::Group) -> Delimiter {
|
fn delimiter(&mut self, group: &Self::Group) -> Delimiter {
|
||||||
group.delimiter
|
group.delimiter
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
|
fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
|
||||||
group.stream.clone()
|
group.stream.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(&mut self, group: &Self::Group) -> Self::Span {
|
fn span(&mut self, group: &Self::Group) -> Self::Span {
|
||||||
group.span.entire()
|
group.span.entire()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_open(&mut self, group: &Self::Group) -> Self::Span {
|
fn span_open(&mut self, group: &Self::Group) -> Self::Span {
|
||||||
group.span.open
|
group.span.open
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_close(&mut self, group: &Self::Group) -> Self::Span {
|
fn span_close(&mut self, group: &Self::Group) -> Self::Span {
|
||||||
group.span.close
|
group.span.close
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
|
fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
|
||||||
group.span = DelimSpan::from_single(span);
|
group.span = DelimSpan::from_single(span);
|
||||||
}
|
}
|
||||||
|
@ -567,15 +581,19 @@ impl server::Punct for Rustc<'_, '_> {
|
||||||
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
|
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
|
||||||
Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
|
Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_char(&mut self, punct: Self::Punct) -> char {
|
fn as_char(&mut self, punct: Self::Punct) -> char {
|
||||||
punct.ch
|
punct.ch
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spacing(&mut self, punct: Self::Punct) -> Spacing {
|
fn spacing(&mut self, punct: Self::Punct) -> Spacing {
|
||||||
if punct.joint { Spacing::Joint } else { Spacing::Alone }
|
if punct.joint { Spacing::Joint } else { Spacing::Alone }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(&mut self, punct: Self::Punct) -> Self::Span {
|
fn span(&mut self, punct: Self::Punct) -> Self::Span {
|
||||||
punct.span
|
punct.span
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
|
fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
|
||||||
Punct { span, ..punct }
|
Punct { span, ..punct }
|
||||||
}
|
}
|
||||||
|
@ -585,9 +603,11 @@ impl server::Ident for Rustc<'_, '_> {
|
||||||
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
|
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
|
||||||
Ident::new(self.sess(), Symbol::intern(string), is_raw, span)
|
Ident::new(self.sess(), Symbol::intern(string), is_raw, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(&mut self, ident: Self::Ident) -> Self::Span {
|
fn span(&mut self, ident: Self::Ident) -> Self::Span {
|
||||||
ident.span
|
ident.span
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
|
fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
|
||||||
Ident { span, ..ident }
|
Ident { span, ..ident }
|
||||||
}
|
}
|
||||||
|
@ -639,45 +659,57 @@ impl server::Literal for Rustc<'_, '_> {
|
||||||
|
|
||||||
Ok(Literal { lit, span: self.call_site })
|
Ok(Literal { lit, span: self.call_site })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string(&mut self, literal: &Self::Literal) -> String {
|
fn to_string(&mut self, literal: &Self::Literal) -> String {
|
||||||
literal.lit.to_string()
|
literal.lit.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_kind(&mut self, literal: &Self::Literal) -> String {
|
fn debug_kind(&mut self, literal: &Self::Literal) -> String {
|
||||||
format!("{:?}", literal.lit.kind)
|
format!("{:?}", literal.lit.kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn symbol(&mut self, literal: &Self::Literal) -> String {
|
fn symbol(&mut self, literal: &Self::Literal) -> String {
|
||||||
literal.lit.symbol.to_string()
|
literal.lit.symbol.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suffix(&mut self, literal: &Self::Literal) -> Option<String> {
|
fn suffix(&mut self, literal: &Self::Literal) -> Option<String> {
|
||||||
literal.lit.suffix.as_ref().map(Symbol::to_string)
|
literal.lit.suffix.as_ref().map(Symbol::to_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn integer(&mut self, n: &str) -> Self::Literal {
|
fn integer(&mut self, n: &str) -> Self::Literal {
|
||||||
self.lit(token::Integer, Symbol::intern(n), None)
|
self.lit(token::Integer, Symbol::intern(n), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
|
fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
|
||||||
self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind)))
|
self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn float(&mut self, n: &str) -> Self::Literal {
|
fn float(&mut self, n: &str) -> Self::Literal {
|
||||||
self.lit(token::Float, Symbol::intern(n), None)
|
self.lit(token::Float, Symbol::intern(n), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f32(&mut self, n: &str) -> Self::Literal {
|
fn f32(&mut self, n: &str) -> Self::Literal {
|
||||||
self.lit(token::Float, Symbol::intern(n), Some(sym::f32))
|
self.lit(token::Float, Symbol::intern(n), Some(sym::f32))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn f64(&mut self, n: &str) -> Self::Literal {
|
fn f64(&mut self, n: &str) -> Self::Literal {
|
||||||
self.lit(token::Float, Symbol::intern(n), Some(sym::f64))
|
self.lit(token::Float, Symbol::intern(n), Some(sym::f64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string(&mut self, string: &str) -> Self::Literal {
|
fn string(&mut self, string: &str) -> Self::Literal {
|
||||||
let quoted = format!("{:?}", string);
|
let quoted = format!("{:?}", string);
|
||||||
assert!(quoted.starts_with('"') && quoted.ends_with('"'));
|
assert!(quoted.starts_with('"') && quoted.ends_with('"'));
|
||||||
let symbol = "ed[1..quoted.len() - 1];
|
let symbol = "ed[1..quoted.len() - 1];
|
||||||
self.lit(token::Str, Symbol::intern(symbol), None)
|
self.lit(token::Str, Symbol::intern(symbol), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn character(&mut self, ch: char) -> Self::Literal {
|
fn character(&mut self, ch: char) -> Self::Literal {
|
||||||
let quoted = format!("{:?}", ch);
|
let quoted = format!("{:?}", ch);
|
||||||
assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
|
assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
|
||||||
let symbol = "ed[1..quoted.len() - 1];
|
let symbol = "ed[1..quoted.len() - 1];
|
||||||
self.lit(token::Char, Symbol::intern(symbol), None)
|
self.lit(token::Char, Symbol::intern(symbol), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
|
fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
|
||||||
let string = bytes
|
let string = bytes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -687,12 +719,15 @@ impl server::Literal for Rustc<'_, '_> {
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
self.lit(token::ByteStr, Symbol::intern(&string), None)
|
self.lit(token::ByteStr, Symbol::intern(&string), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(&mut self, literal: &Self::Literal) -> Self::Span {
|
fn span(&mut self, literal: &Self::Literal) -> Self::Span {
|
||||||
literal.span
|
literal.span
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
|
fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
|
||||||
literal.span = span;
|
literal.span = span;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subspan(
|
fn subspan(
|
||||||
&mut self,
|
&mut self,
|
||||||
literal: &Self::Literal,
|
literal: &Self::Literal,
|
||||||
|
@ -735,6 +770,7 @@ impl server::SourceFile for Rustc<'_, '_> {
|
||||||
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
|
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
|
||||||
Lrc::ptr_eq(file1, file2)
|
Lrc::ptr_eq(file1, file2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&mut self, file: &Self::SourceFile) -> String {
|
fn path(&mut self, file: &Self::SourceFile) -> String {
|
||||||
match file.name {
|
match file.name {
|
||||||
FileName::Real(ref name) => name
|
FileName::Real(ref name) => name
|
||||||
|
@ -746,6 +782,7 @@ impl server::SourceFile for Rustc<'_, '_> {
|
||||||
_ => file.name.prefer_local().to_string(),
|
_ => file.name.prefer_local().to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_real(&mut self, file: &Self::SourceFile) -> bool {
|
fn is_real(&mut self, file: &Self::SourceFile) -> bool {
|
||||||
file.is_real_file()
|
file.is_real_file()
|
||||||
}
|
}
|
||||||
|
@ -755,6 +792,7 @@ impl server::MultiSpan for Rustc<'_, '_> {
|
||||||
fn new(&mut self) -> Self::MultiSpan {
|
fn new(&mut self) -> Self::MultiSpan {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
|
fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
|
||||||
spans.push(span)
|
spans.push(span)
|
||||||
}
|
}
|
||||||
|
@ -766,6 +804,7 @@ impl server::Diagnostic for Rustc<'_, '_> {
|
||||||
diag.set_span(MultiSpan::from_spans(spans));
|
diag.set_span(MultiSpan::from_spans(spans));
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub(
|
fn sub(
|
||||||
&mut self,
|
&mut self,
|
||||||
diag: &mut Self::Diagnostic,
|
diag: &mut Self::Diagnostic,
|
||||||
|
@ -775,6 +814,7 @@ impl server::Diagnostic for Rustc<'_, '_> {
|
||||||
) {
|
) {
|
||||||
diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
|
diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(&mut self, mut diag: Self::Diagnostic) {
|
fn emit(&mut self, mut diag: Self::Diagnostic) {
|
||||||
self.sess().span_diagnostic.emit_diagnostic(&mut diag);
|
self.sess().span_diagnostic.emit_diagnostic(&mut diag);
|
||||||
}
|
}
|
||||||
|
@ -788,38 +828,49 @@ impl server::Span for Rustc<'_, '_> {
|
||||||
format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
|
format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn def_site(&mut self) -> Self::Span {
|
fn def_site(&mut self) -> Self::Span {
|
||||||
self.def_site
|
self.def_site
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_site(&mut self) -> Self::Span {
|
fn call_site(&mut self) -> Self::Span {
|
||||||
self.call_site
|
self.call_site
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mixed_site(&mut self) -> Self::Span {
|
fn mixed_site(&mut self) -> Self::Span {
|
||||||
self.mixed_site
|
self.mixed_site
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
|
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
|
||||||
self.sess().source_map().lookup_char_pos(span.lo()).file
|
self.sess().source_map().lookup_char_pos(span.lo()).file
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
|
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
|
||||||
span.parent_callsite()
|
span.parent_callsite()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source(&mut self, span: Self::Span) -> Self::Span {
|
fn source(&mut self, span: Self::Span) -> Self::Span {
|
||||||
span.source_callsite()
|
span.source_callsite()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(&mut self, span: Self::Span) -> LineColumn {
|
fn start(&mut self, span: Self::Span) -> LineColumn {
|
||||||
let loc = self.sess().source_map().lookup_char_pos(span.lo());
|
let loc = self.sess().source_map().lookup_char_pos(span.lo());
|
||||||
LineColumn { line: loc.line, column: loc.col.to_usize() }
|
LineColumn { line: loc.line, column: loc.col.to_usize() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(&mut self, span: Self::Span) -> LineColumn {
|
fn end(&mut self, span: Self::Span) -> LineColumn {
|
||||||
let loc = self.sess().source_map().lookup_char_pos(span.hi());
|
let loc = self.sess().source_map().lookup_char_pos(span.hi());
|
||||||
LineColumn { line: loc.line, column: loc.col.to_usize() }
|
LineColumn { line: loc.line, column: loc.col.to_usize() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before(&mut self, span: Self::Span) -> Self::Span {
|
fn before(&mut self, span: Self::Span) -> Self::Span {
|
||||||
span.shrink_to_lo()
|
span.shrink_to_lo()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after(&mut self, span: Self::Span) -> Self::Span {
|
fn after(&mut self, span: Self::Span) -> Self::Span {
|
||||||
span.shrink_to_hi()
|
span.shrink_to_hi()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
|
fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
|
||||||
let self_loc = self.sess().source_map().lookup_char_pos(first.lo());
|
let self_loc = self.sess().source_map().lookup_char_pos(first.lo());
|
||||||
let other_loc = self.sess().source_map().lookup_char_pos(second.lo());
|
let other_loc = self.sess().source_map().lookup_char_pos(second.lo());
|
||||||
|
@ -830,9 +881,11 @@ impl server::Span for Rustc<'_, '_> {
|
||||||
|
|
||||||
Some(first.to(second))
|
Some(first.to(second))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
|
fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
|
||||||
span.with_ctxt(at.ctxt())
|
span.with_ctxt(at.ctxt())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_text(&mut self, span: Self::Span) -> Option<String> {
|
fn source_text(&mut self, span: Self::Span) -> Option<String> {
|
||||||
self.sess().source_map().span_to_snippet(span).ok()
|
self.sess().source_map().span_to_snippet(span).ok()
|
||||||
}
|
}
|
||||||
|
@ -863,6 +916,7 @@ impl server::Span for Rustc<'_, '_> {
|
||||||
fn save_span(&mut self, span: Self::Span) -> usize {
|
fn save_span(&mut self, span: Self::Span) -> usize {
|
||||||
self.sess().save_proc_macro_span(span)
|
self.sess().save_proc_macro_span(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
|
fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
|
||||||
let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site);
|
let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site);
|
||||||
*self.rebased_spans.entry(id).or_insert_with(|| {
|
*self.rebased_spans.entry(id).or_insert_with(|| {
|
||||||
|
|
|
@ -4,7 +4,6 @@ use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree};
|
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree};
|
||||||
use rustc_span::create_default_session_globals_then;
|
use rustc_span::create_default_session_globals_then;
|
||||||
use rustc_span::{BytePos, Span, Symbol};
|
use rustc_span::{BytePos, Span, Symbol};
|
||||||
use smallvec::smallvec;
|
|
||||||
|
|
||||||
fn string_to_ts(string: &str) -> TokenStream {
|
fn string_to_ts(string: &str) -> TokenStream {
|
||||||
string_to_stream(string.to_owned())
|
string_to_stream(string.to_owned())
|
||||||
|
@ -24,7 +23,10 @@ fn test_concat() {
|
||||||
let test_res = string_to_ts("foo::bar::baz");
|
let test_res = string_to_ts("foo::bar::baz");
|
||||||
let test_fst = string_to_ts("foo::bar");
|
let test_fst = string_to_ts("foo::bar");
|
||||||
let test_snd = string_to_ts("::baz");
|
let test_snd = string_to_ts("::baz");
|
||||||
let eq_res = TokenStream::from_streams(smallvec![test_fst, test_snd]);
|
let mut builder = TokenStreamBuilder::new();
|
||||||
|
builder.push(test_fst);
|
||||||
|
builder.push(test_snd);
|
||||||
|
let eq_res = builder.build();
|
||||||
assert_eq!(test_res.trees().count(), 5);
|
assert_eq!(test_res.trees().count(), 5);
|
||||||
assert_eq!(eq_res.trees().count(), 5);
|
assert_eq!(eq_res.trees().count(), 5);
|
||||||
assert_eq!(test_res.eq_unspanned(&eq_res), true);
|
assert_eq!(test_res.eq_unspanned(&eq_res), true);
|
||||||
|
|
|
@ -662,7 +662,11 @@ where
|
||||||
match b.kind() {
|
match b.kind() {
|
||||||
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
|
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
|
||||||
// Forbid inference variables in the RHS.
|
// Forbid inference variables in the RHS.
|
||||||
bug!("unexpected inference var {:?}", b)
|
self.infcx.tcx.sess.delay_span_bug(
|
||||||
|
self.delegate.span(),
|
||||||
|
format!("unexpected inference var {:?}", b,),
|
||||||
|
);
|
||||||
|
Ok(a)
|
||||||
}
|
}
|
||||||
// FIXME(invariance): see the related FIXME above.
|
// FIXME(invariance): see the related FIXME above.
|
||||||
_ => self.infcx.super_combine_consts(self, a, b),
|
_ => self.infcx.super_combine_consts(self, a, b),
|
||||||
|
|
|
@ -371,6 +371,13 @@ where
|
||||||
Ok(self.fold_const(c))
|
Ok(self.fold_const(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_fold_unevaluated(
|
||||||
|
&mut self,
|
||||||
|
c: ty::Unevaluated<'tcx>,
|
||||||
|
) -> Result<ty::Unevaluated<'tcx>, Self::Error> {
|
||||||
|
Ok(self.fold_unevaluated(c))
|
||||||
|
}
|
||||||
|
|
||||||
fn try_fold_predicate(
|
fn try_fold_predicate(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: ty::Predicate<'tcx>,
|
p: ty::Predicate<'tcx>,
|
||||||
|
|
|
@ -259,7 +259,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let cycle = self.resolve_vars_if_possible(cycle.to_owned());
|
let cycle = self.resolve_vars_if_possible(cycle.to_owned());
|
||||||
assert!(!cycle.is_empty());
|
assert!(!cycle.is_empty());
|
||||||
|
|
||||||
debug!("report_overflow_error_cycle: cycle={:?}", cycle);
|
debug!(?cycle, "report_overflow_error_cycle");
|
||||||
|
|
||||||
// The 'deepest' obligation is most likely to have a useful
|
// The 'deepest' obligation is most likely to have a useful
|
||||||
// cause 'backtrace'
|
// cause 'backtrace'
|
||||||
|
@ -1513,6 +1513,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn report_projection_error(
|
fn report_projection_error(
|
||||||
&self,
|
&self,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
@ -1551,15 +1552,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
&mut obligations,
|
&mut obligations,
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!(
|
debug!(?obligation.cause, ?obligation.param_env);
|
||||||
"report_projection_error obligation.cause={:?} obligation.param_env={:?}",
|
|
||||||
obligation.cause, obligation.param_env
|
|
||||||
);
|
|
||||||
|
|
||||||
debug!(
|
debug!(?normalized_ty, data.ty = ?data.term);
|
||||||
"report_projection_error normalized_ty={:?} data.ty={:?}",
|
|
||||||
normalized_ty, data.term,
|
|
||||||
);
|
|
||||||
|
|
||||||
let is_normalized_ty_expected = !matches!(
|
let is_normalized_ty_expected = !matches!(
|
||||||
obligation.cause.code().peel_derives(),
|
obligation.cause.code().peel_derives(),
|
||||||
|
@ -2346,6 +2341,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn suggest_unsized_bound_if_applicable(
|
fn suggest_unsized_bound_if_applicable(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -2360,10 +2356,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
debug!(
|
debug!(?pred, ?item_def_id, ?span);
|
||||||
"suggest_unsized_bound_if_applicable: pred={:?} item_def_id={:?} span={:?}",
|
|
||||||
pred, item_def_id, span
|
|
||||||
);
|
|
||||||
|
|
||||||
let (Some(node), true) = (
|
let (Some(node), true) = (
|
||||||
self.tcx.hir().get_if_local(item_def_id),
|
self.tcx.hir().get_if_local(item_def_id),
|
||||||
|
@ -2374,6 +2367,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
self.maybe_suggest_unsized_generics(err, span, node);
|
self.maybe_suggest_unsized_generics(err, span, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn maybe_suggest_unsized_generics<'hir>(
|
fn maybe_suggest_unsized_generics<'hir>(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -2384,8 +2378,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let sized_trait = self.tcx.lang_items().sized_trait();
|
let sized_trait = self.tcx.lang_items().sized_trait();
|
||||||
debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params);
|
debug!(?generics.params);
|
||||||
debug!("maybe_suggest_unsized_generics: generics.predicates={:?}", generics.predicates);
|
debug!(?generics.predicates);
|
||||||
let Some(param) = generics.params.iter().find(|param| param.span == span) else {
|
let Some(param) = generics.params.iter().find(|param| param.span == span) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -2399,7 +2393,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
if explicitly_sized {
|
if explicitly_sized {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug!("maybe_suggest_unsized_generics: param={:?}", param);
|
debug!(?param);
|
||||||
match node {
|
match node {
|
||||||
hir::Node::Item(
|
hir::Node::Item(
|
||||||
item @ hir::Item {
|
item @ hir::Item {
|
||||||
|
@ -2517,7 +2511,7 @@ impl<'v> Visitor<'v> for FindTypeParam {
|
||||||
if path.segments.len() == 1 && path.segments[0].ident.name == self.param =>
|
if path.segments.len() == 1 && path.segments[0].ident.name == self.param =>
|
||||||
{
|
{
|
||||||
if !self.nested {
|
if !self.nested {
|
||||||
debug!("FindTypeParam::visit_ty: ty={:?}", ty);
|
debug!(?ty, "FindTypeParam::visit_ty");
|
||||||
self.invalid_spans.push(ty.span);
|
self.invalid_spans.push(ty.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1628,16 +1628,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Returns `true` if an async-await specific note was added to the diagnostic.
|
/// Returns `true` if an async-await specific note was added to the diagnostic.
|
||||||
|
#[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))]
|
||||||
fn maybe_note_obligation_cause_for_async_await(
|
fn maybe_note_obligation_cause_for_async_await(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!(
|
|
||||||
"maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
|
|
||||||
obligation.cause.span={:?}",
|
|
||||||
obligation.predicate, obligation.cause.span
|
|
||||||
);
|
|
||||||
let hir = self.tcx.hir();
|
let hir = self.tcx.hir();
|
||||||
|
|
||||||
// Attempt to detect an async-await error by looking at the obligation causes, looking
|
// Attempt to detect an async-await error by looking at the obligation causes, looking
|
||||||
|
@ -1677,7 +1673,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let mut seen_upvar_tys_infer_tuple = false;
|
let mut seen_upvar_tys_infer_tuple = false;
|
||||||
|
|
||||||
while let Some(code) = next_code {
|
while let Some(code) = next_code {
|
||||||
debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
|
debug!(?code);
|
||||||
match code {
|
match code {
|
||||||
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
|
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
|
||||||
next_code = Some(parent_code);
|
next_code = Some(parent_code);
|
||||||
|
@ -1685,10 +1681,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
ObligationCauseCode::ImplDerivedObligation(cause) => {
|
ObligationCauseCode::ImplDerivedObligation(cause) => {
|
||||||
let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
|
let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
|
||||||
debug!(
|
debug!(
|
||||||
"maybe_note_obligation_cause_for_async_await: ImplDerived \
|
parent_trait_ref = ?cause.derived.parent_trait_pred,
|
||||||
parent_trait_ref={:?} self_ty.kind={:?}",
|
self_ty.kind = ?ty.kind(),
|
||||||
cause.derived.parent_trait_pred,
|
"ImplDerived",
|
||||||
ty.kind()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
|
@ -1717,10 +1712,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
| ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
|
| ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
|
||||||
let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
|
let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty();
|
||||||
debug!(
|
debug!(
|
||||||
"maybe_note_obligation_cause_for_async_await: \
|
parent_trait_ref = ?derived_obligation.parent_trait_pred,
|
||||||
parent_trait_ref={:?} self_ty.kind={:?}",
|
self_ty.kind = ?ty.kind(),
|
||||||
derived_obligation.parent_trait_pred,
|
|
||||||
ty.kind()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
|
@ -1750,7 +1743,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only continue if a generator was found.
|
// Only continue if a generator was found.
|
||||||
debug!(?generator, ?trait_ref, ?target_ty, "maybe_note_obligation_cause_for_async_await");
|
debug!(?generator, ?trait_ref, ?target_ty);
|
||||||
let (Some(generator_did), Some(trait_ref), Some(target_ty)) = (generator, trait_ref, target_ty) else {
|
let (Some(generator_did), Some(trait_ref), Some(target_ty)) = (generator, trait_ref, target_ty) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -1760,12 +1753,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow());
|
let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow());
|
||||||
let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
|
let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
|
||||||
debug!(
|
debug!(
|
||||||
"maybe_note_obligation_cause_for_async_await: generator_did={:?} \
|
?generator_did,
|
||||||
generator_did_root={:?} in_progress_typeck_results.hir_owner={:?} span={:?}",
|
?generator_did_root,
|
||||||
generator_did,
|
in_progress_typeck_results.hir_owner = ?in_progress_typeck_results.as_ref().map(|t| t.hir_owner),
|
||||||
generator_did_root,
|
?span,
|
||||||
in_progress_typeck_results.as_ref().map(|t| t.hir_owner),
|
|
||||||
span
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let generator_body = generator_did
|
let generator_body = generator_did
|
||||||
|
@ -1788,7 +1779,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
if let Some(body) = generator_body {
|
if let Some(body) = generator_body {
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
}
|
}
|
||||||
debug!("maybe_note_obligation_cause_for_async_await: awaits = {:?}", visitor.awaits);
|
debug!(awaits = ?visitor.awaits);
|
||||||
|
|
||||||
// Look for a type inside the generator interior that matches the target type to get
|
// Look for a type inside the generator interior that matches the target type to get
|
||||||
// a span.
|
// a span.
|
||||||
|
@ -1809,11 +1800,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let ty_erased = self.tcx.erase_late_bound_regions(ty);
|
let ty_erased = self.tcx.erase_late_bound_regions(ty);
|
||||||
let ty_erased = self.tcx.erase_regions(ty_erased);
|
let ty_erased = self.tcx.erase_regions(ty_erased);
|
||||||
let eq = ty_erased == target_ty_erased;
|
let eq = ty_erased == target_ty_erased;
|
||||||
debug!(
|
debug!(?ty_erased, ?target_ty_erased, ?eq);
|
||||||
"maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
|
|
||||||
target_ty_erased={:?} eq={:?}",
|
|
||||||
ty_erased, target_ty_erased, eq
|
|
||||||
);
|
|
||||||
eq
|
eq
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1888,6 +1875,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
/// Unconditionally adds the diagnostic note described in
|
/// Unconditionally adds the diagnostic note described in
|
||||||
/// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
|
/// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
|
||||||
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn note_obligation_cause_for_async_await(
|
fn note_obligation_cause_for_async_await(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -2037,8 +2025,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
// Look at the last interior type to get a span for the `.await`.
|
// Look at the last interior type to get a span for the `.await`.
|
||||||
debug!(
|
debug!(
|
||||||
"note_obligation_cause_for_async_await generator_interior_types: {:#?}",
|
generator_interior_types = ?format_args!(
|
||||||
typeck_results.as_ref().map(|t| &t.generator_interior_types)
|
"{:#?}", typeck_results.as_ref().map(|t| &t.generator_interior_types)
|
||||||
|
),
|
||||||
);
|
);
|
||||||
explain_yield(interior_span, yield_span, scope_span);
|
explain_yield(interior_span, yield_span, scope_span);
|
||||||
}
|
}
|
||||||
|
@ -2073,7 +2062,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
// bar(Foo(std::ptr::null())).await;
|
// bar(Foo(std::ptr::null())).await;
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
|
// ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
|
||||||
// ```
|
// ```
|
||||||
debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
|
debug!(parent_def_kind = ?self.tcx.def_kind(parent_did));
|
||||||
let is_raw_borrow_inside_fn_like_call =
|
let is_raw_borrow_inside_fn_like_call =
|
||||||
match self.tcx.def_kind(parent_did) {
|
match self.tcx.def_kind(parent_did) {
|
||||||
DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
|
DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
|
||||||
|
@ -2131,7 +2120,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// Add a note for the item obligation that remains - normally a note pointing to the
|
// Add a note for the item obligation that remains - normally a note pointing to the
|
||||||
// bound that introduced the obligation (e.g. `T: Send`).
|
// bound that introduced the obligation (e.g. `T: Send`).
|
||||||
debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
|
debug!(?next_code);
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
err,
|
err,
|
||||||
&obligation.predicate,
|
&obligation.predicate,
|
||||||
|
@ -2688,6 +2677,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(
|
||||||
|
level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
|
||||||
|
)]
|
||||||
fn suggest_await_before_try(
|
fn suggest_await_before_try(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -2695,13 +2687,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
debug!(
|
|
||||||
"suggest_await_before_try: obligation={:?}, span={:?}, trait_pred={:?}, trait_pred_self_ty={:?}",
|
|
||||||
obligation,
|
|
||||||
span,
|
|
||||||
trait_pred,
|
|
||||||
trait_pred.self_ty()
|
|
||||||
);
|
|
||||||
let body_hir_id = obligation.cause.body_id;
|
let body_hir_id = obligation.cause.body_id;
|
||||||
let item_id = self.tcx.hir().get_parent_node(body_hir_id);
|
let item_id = self.tcx.hir().get_parent_node(body_hir_id);
|
||||||
|
|
||||||
|
@ -2739,14 +2724,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"suggest_await_before_try: normalized_projection_type {:?}",
|
normalized_projection_type = ?self.resolve_vars_if_possible(projection_ty)
|
||||||
self.resolve_vars_if_possible(projection_ty)
|
|
||||||
);
|
);
|
||||||
let try_obligation = self.mk_trait_obligation_with_new_self_ty(
|
let try_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
|
trait_pred.map_bound(|trait_pred| (trait_pred, projection_ty.skip_binder())),
|
||||||
);
|
);
|
||||||
debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
|
debug!(try_trait_obligation = ?try_obligation);
|
||||||
if self.predicate_may_hold(&try_obligation)
|
if self.predicate_may_hold(&try_obligation)
|
||||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||||
&& snippet.ends_with('?')
|
&& snippet.ends_with('?')
|
||||||
|
|
|
@ -1144,7 +1144,7 @@ extern "rust-intrinsic" {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
|
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
|
||||||
#[rustc_diagnostic_item = "transmute"]
|
#[rustc_diagnostic_item = "transmute"]
|
||||||
pub fn transmute<T, U>(e: T) -> U;
|
pub fn transmute<T, U>(e: T) -> U;
|
||||||
|
|
||||||
|
|
|
@ -1240,8 +1240,8 @@ impl<'a> IoSlice<'a> {
|
||||||
/// use std::io::IoSlice;
|
/// use std::io::IoSlice;
|
||||||
/// use std::ops::Deref;
|
/// use std::ops::Deref;
|
||||||
///
|
///
|
||||||
/// let mut data = [1; 8];
|
/// let data = [1; 8];
|
||||||
/// let mut buf = IoSlice::new(&mut data);
|
/// let mut buf = IoSlice::new(&data);
|
||||||
///
|
///
|
||||||
/// // Mark 3 bytes as read.
|
/// // Mark 3 bytes as read.
|
||||||
/// buf.advance(3);
|
/// buf.advance(3);
|
||||||
|
@ -1435,10 +1435,10 @@ pub trait Write {
|
||||||
/// use std::fs::File;
|
/// use std::fs::File;
|
||||||
///
|
///
|
||||||
/// fn main() -> std::io::Result<()> {
|
/// fn main() -> std::io::Result<()> {
|
||||||
/// let mut data1 = [1; 8];
|
/// let data1 = [1; 8];
|
||||||
/// let mut data2 = [15; 8];
|
/// let data2 = [15; 8];
|
||||||
/// let io_slice1 = IoSlice::new(&mut data1);
|
/// let io_slice1 = IoSlice::new(&data1);
|
||||||
/// let io_slice2 = IoSlice::new(&mut data2);
|
/// let io_slice2 = IoSlice::new(&data2);
|
||||||
///
|
///
|
||||||
/// let mut buffer = File::create("foo.txt")?;
|
/// let mut buffer = File::create("foo.txt")?;
|
||||||
///
|
///
|
||||||
|
|
|
@ -583,8 +583,8 @@ impl<'a> SocketAncillary<'a> {
|
||||||
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
|
||||||
/// ancillary.add_fds(&[sock.as_raw_fd()][..]);
|
/// ancillary.add_fds(&[sock.as_raw_fd()][..]);
|
||||||
///
|
///
|
||||||
/// let mut buf = [1; 8];
|
/// let buf = [1; 8];
|
||||||
/// let mut bufs = &mut [IoSlice::new(&mut buf[..])][..];
|
/// let mut bufs = &mut [IoSlice::new(&buf[..])][..];
|
||||||
/// sock.send_vectored_with_ancillary(bufs, &mut ancillary)?;
|
/// sock.send_vectored_with_ancillary(bufs, &mut ancillary)?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
|
|
|
@ -46,13 +46,12 @@ impl Drop for StaticMutexGuard {
|
||||||
|
|
||||||
/// An OS-based mutual exclusion lock.
|
/// An OS-based mutual exclusion lock.
|
||||||
///
|
///
|
||||||
/// This mutex does *not* have a const constructor, cleans up its resources in
|
/// This mutex cleans up its resources in its `Drop` implementation, may safely
|
||||||
/// its `Drop` implementation, may safely be moved (when not borrowed), and
|
/// be moved (when not borrowed), and does not cause UB when used reentrantly.
|
||||||
/// does not cause UB when used reentrantly.
|
|
||||||
///
|
///
|
||||||
/// This mutex does not implement poisoning.
|
/// This mutex does not implement poisoning.
|
||||||
///
|
///
|
||||||
/// This is either a wrapper around `Box<imp::Mutex>` or `imp::Mutex`,
|
/// This is either a wrapper around `LazyBox<imp::Mutex>` or `imp::Mutex`,
|
||||||
/// depending on the platform. It is boxed on platforms where `imp::Mutex` may
|
/// depending on the platform. It is boxed on platforms where `imp::Mutex` may
|
||||||
/// not be moved.
|
/// not be moved.
|
||||||
pub struct MovableMutex(imp::MovableMutex);
|
pub struct MovableMutex(imp::MovableMutex);
|
||||||
|
|
|
@ -62,12 +62,12 @@ impl Drop for StaticRwLockWriteGuard {
|
||||||
|
|
||||||
/// An OS-based reader-writer lock.
|
/// An OS-based reader-writer lock.
|
||||||
///
|
///
|
||||||
/// This rwlock does *not* have a const constructor, cleans up its resources in
|
/// This rwlock cleans up its resources in its `Drop` implementation and may
|
||||||
/// its `Drop` implementation and may safely be moved (when not borrowed).
|
/// safely be moved (when not borrowed).
|
||||||
///
|
///
|
||||||
/// This rwlock does not implement poisoning.
|
/// This rwlock does not implement poisoning.
|
||||||
///
|
///
|
||||||
/// This is either a wrapper around `Box<imp::RwLock>` or `imp::RwLock`,
|
/// This is either a wrapper around `LazyBox<imp::RwLock>` or `imp::RwLock`,
|
||||||
/// depending on the platform. It is boxed on platforms where `imp::RwLock` may
|
/// depending on the platform. It is boxed on platforms where `imp::RwLock` may
|
||||||
/// not be moved.
|
/// not be moved.
|
||||||
pub struct MovableRwLock(imp::MovableRwLock);
|
pub struct MovableRwLock(imp::MovableRwLock);
|
||||||
|
|
|
@ -1487,13 +1487,14 @@ impl<T> JoinHandle<T> {
|
||||||
|
|
||||||
/// Checks if the associated thread has finished running its main function.
|
/// Checks if the associated thread has finished running its main function.
|
||||||
///
|
///
|
||||||
|
/// `is_finished` supports implementing a non-blocking join operation, by checking
|
||||||
|
/// `is_finished`, and calling `join` if it returns `true`. This function does not block. To
|
||||||
|
/// block while waiting on the thread to finish, use [`join`][Self::join].
|
||||||
|
///
|
||||||
/// This might return `true` for a brief moment after the thread's main
|
/// This might return `true` for a brief moment after the thread's main
|
||||||
/// function has returned, but before the thread itself has stopped running.
|
/// function has returned, but before the thread itself has stopped running.
|
||||||
/// However, once this returns `true`, [`join`][Self::join] can be expected
|
/// However, once this returns `true`, [`join`][Self::join] can be expected
|
||||||
/// to return quickly, without blocking for any significant amount of time.
|
/// to return quickly, without blocking for any significant amount of time.
|
||||||
///
|
|
||||||
/// This function does not block. To block while waiting on the thread to finish,
|
|
||||||
/// use [`join`][Self::join].
|
|
||||||
#[stable(feature = "thread_is_running", since = "1.61.0")]
|
#[stable(feature = "thread_is_running", since = "1.61.0")]
|
||||||
pub fn is_finished(&self) -> bool {
|
pub fn is_finished(&self) -> bool {
|
||||||
Arc::strong_count(&self.0.packet) == 1
|
Arc::strong_count(&self.0.packet) == 1
|
||||||
|
|
|
@ -308,13 +308,14 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
|
||||||
|
|
||||||
/// Checks if the associated thread has finished running its main function.
|
/// Checks if the associated thread has finished running its main function.
|
||||||
///
|
///
|
||||||
|
/// `is_finished` supports implementing a non-blocking join operation, by checking
|
||||||
|
/// `is_finished`, and calling `join` if it returns `false`. This function does not block. To
|
||||||
|
/// block while waiting on the thread to finish, use [`join`][Self::join].
|
||||||
|
///
|
||||||
/// This might return `true` for a brief moment after the thread's main
|
/// This might return `true` for a brief moment after the thread's main
|
||||||
/// function has returned, but before the thread itself has stopped running.
|
/// function has returned, but before the thread itself has stopped running.
|
||||||
/// However, once this returns `true`, [`join`][Self::join] can be expected
|
/// However, once this returns `true`, [`join`][Self::join] can be expected
|
||||||
/// to return quickly, without blocking for any significant amount of time.
|
/// to return quickly, without blocking for any significant amount of time.
|
||||||
///
|
|
||||||
/// This function does not block. To block while waiting on the thread to finish,
|
|
||||||
/// use [`join`][Self::join].
|
|
||||||
#[stable(feature = "scoped_threads", since = "1.63.0")]
|
#[stable(feature = "scoped_threads", since = "1.63.0")]
|
||||||
pub fn is_finished(&self) -> bool {
|
pub fn is_finished(&self) -> bool {
|
||||||
Arc::strong_count(&self.0.packet) == 1
|
Arc::strong_count(&self.0.packet) == 1
|
||||||
|
|
|
@ -31,8 +31,6 @@ pub(crate) struct Page<'a> {
|
||||||
pub(crate) description: &'a str,
|
pub(crate) description: &'a str,
|
||||||
pub(crate) keywords: &'a str,
|
pub(crate) keywords: &'a str,
|
||||||
pub(crate) resource_suffix: &'a str,
|
pub(crate) resource_suffix: &'a str,
|
||||||
pub(crate) extra_scripts: &'a [&'a str],
|
|
||||||
pub(crate) static_extra_scripts: &'a [&'a str],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Page<'a> {
|
impl<'a> Page<'a> {
|
||||||
|
|
|
@ -211,8 +211,6 @@ impl<'tcx> Context<'tcx> {
|
||||||
description: &desc,
|
description: &desc,
|
||||||
keywords: &keywords,
|
keywords: &keywords,
|
||||||
resource_suffix: &clone_shared.resource_suffix,
|
resource_suffix: &clone_shared.resource_suffix,
|
||||||
extra_scripts: &[],
|
|
||||||
static_extra_scripts: &[],
|
|
||||||
};
|
};
|
||||||
let mut page_buffer = Buffer::html();
|
let mut page_buffer = Buffer::html();
|
||||||
print_item(self, it, &mut page_buffer, &page);
|
print_item(self, it, &mut page_buffer, &page);
|
||||||
|
@ -568,8 +566,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||||
description: "List of all items in this crate",
|
description: "List of all items in this crate",
|
||||||
keywords: BASIC_KEYWORDS,
|
keywords: BASIC_KEYWORDS,
|
||||||
resource_suffix: &shared.resource_suffix,
|
resource_suffix: &shared.resource_suffix,
|
||||||
extra_scripts: &[],
|
|
||||||
static_extra_scripts: &[],
|
|
||||||
};
|
};
|
||||||
let sidebar = if shared.cache.crate_version.is_some() {
|
let sidebar = if shared.cache.crate_version.is_some() {
|
||||||
format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
|
format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
|
||||||
|
@ -693,7 +689,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||||
else { unreachable!() };
|
else { unreachable!() };
|
||||||
let items = self.build_sidebar_items(module);
|
let items = self.build_sidebar_items(module);
|
||||||
let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix));
|
let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix));
|
||||||
let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
|
let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap());
|
||||||
self.shared.fs.write(js_dst, v)?;
|
self.shared.fs.write(js_dst, v)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -56,7 +56,7 @@ use rustc_middle::middle::stability;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
symbol::{kw, sym, Symbol},
|
symbol::{sym, Symbol},
|
||||||
BytePos, FileName, RealFileName,
|
BytePos, FileName, RealFileName,
|
||||||
};
|
};
|
||||||
use serde::ser::SerializeSeq;
|
use serde::ser::SerializeSeq;
|
||||||
|
@ -1738,8 +1738,6 @@ pub(crate) fn render_impl_summary(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
|
fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
|
||||||
let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 };
|
|
||||||
|
|
||||||
if it.is_struct()
|
if it.is_struct()
|
||||||
|| it.is_trait()
|
|| it.is_trait()
|
||||||
|| it.is_primitive()
|
|| it.is_primitive()
|
||||||
|
@ -1800,21 +1798,6 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
|
||||||
write!(buffer, "<h2 class=\"location\"><a href=\"index.html\">In {}</a></h2>", path);
|
write!(buffer, "<h2 class=\"location\"><a href=\"index.html\">In {}</a></h2>", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sidebar refers to the enclosing module, not this module.
|
|
||||||
let relpath = if it.is_mod() && parentlen != 0 { "./" } else { "" };
|
|
||||||
write!(
|
|
||||||
buffer,
|
|
||||||
"<div id=\"sidebar-vars\" data-name=\"{name}\" data-ty=\"{ty}\" data-relpath=\"{path}\">\
|
|
||||||
</div>",
|
|
||||||
name = it.name.unwrap_or(kw::Empty),
|
|
||||||
ty = it.type_(),
|
|
||||||
path = relpath
|
|
||||||
);
|
|
||||||
write!(
|
|
||||||
buffer,
|
|
||||||
"<script defer src=\"{}sidebar-items{}.js\"></script>",
|
|
||||||
relpath, cx.shared.resource_suffix
|
|
||||||
);
|
|
||||||
// Closes sidebar-elems div.
|
// Closes sidebar-elems div.
|
||||||
buffer.write_str("</div>");
|
buffer.write_str("</div>");
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,8 +475,6 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
|
||||||
description: "List of crates",
|
description: "List of crates",
|
||||||
keywords: BASIC_KEYWORDS,
|
keywords: BASIC_KEYWORDS,
|
||||||
resource_suffix: &shared.resource_suffix,
|
resource_suffix: &shared.resource_suffix,
|
||||||
extra_scripts: &[],
|
|
||||||
static_extra_scripts: &[],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let content = format!(
|
let content = format!(
|
||||||
|
|
|
@ -203,8 +203,6 @@ impl SourceCollector<'_, '_> {
|
||||||
description: &desc,
|
description: &desc,
|
||||||
keywords: BASIC_KEYWORDS,
|
keywords: BASIC_KEYWORDS,
|
||||||
resource_suffix: &shared.resource_suffix,
|
resource_suffix: &shared.resource_suffix,
|
||||||
extra_scripts: &[&format!("source-files{}", shared.resource_suffix)],
|
|
||||||
static_extra_scripts: &[&format!("source-script{}", shared.resource_suffix)],
|
|
||||||
};
|
};
|
||||||
let v = layout::render(
|
let v = layout::render(
|
||||||
&shared.layout,
|
&shared.layout,
|
||||||
|
|
|
@ -66,16 +66,9 @@ function showMain() {
|
||||||
(function() {
|
(function() {
|
||||||
window.rootPath = getVar("root-path");
|
window.rootPath = getVar("root-path");
|
||||||
window.currentCrate = getVar("current-crate");
|
window.currentCrate = getVar("current-crate");
|
||||||
window.searchJS = resourcePath("search", ".js");
|
}());
|
||||||
window.searchIndexJS = resourcePath("search-index", ".js");
|
|
||||||
window.settingsJS = resourcePath("settings", ".js");
|
function setMobileTopbar() {
|
||||||
const sidebarVars = document.getElementById("sidebar-vars");
|
|
||||||
if (sidebarVars) {
|
|
||||||
window.sidebarCurrent = {
|
|
||||||
name: sidebarVars.attributes["data-name"].value,
|
|
||||||
ty: sidebarVars.attributes["data-ty"].value,
|
|
||||||
relpath: sidebarVars.attributes["data-relpath"].value,
|
|
||||||
};
|
|
||||||
// FIXME: It would be nicer to generate this text content directly in HTML,
|
// FIXME: It would be nicer to generate this text content directly in HTML,
|
||||||
// but with the current code it's hard to get the right information in the right place.
|
// but with the current code it's hard to get the right information in the right place.
|
||||||
const mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
|
const mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
|
||||||
|
@ -83,8 +76,7 @@ function showMain() {
|
||||||
if (mobileLocationTitle && locationTitle) {
|
if (mobileLocationTitle && locationTitle) {
|
||||||
mobileLocationTitle.innerHTML = locationTitle.innerHTML;
|
mobileLocationTitle.innerHTML = locationTitle.innerHTML;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}());
|
|
||||||
|
|
||||||
// Gets the human-readable string for the virtual-key code of the
|
// Gets the human-readable string for the virtual-key code of the
|
||||||
// given KeyboardEvent, ev.
|
// given KeyboardEvent, ev.
|
||||||
|
@ -227,7 +219,7 @@ function loadCss(cssFileName) {
|
||||||
// Sending request for the CSS and the JS files at the same time so it will
|
// Sending request for the CSS and the JS files at the same time so it will
|
||||||
// hopefully be loaded when the JS will generate the settings content.
|
// hopefully be loaded when the JS will generate the settings content.
|
||||||
loadCss("settings");
|
loadCss("settings");
|
||||||
loadScript(window.settingsJS);
|
loadScript(resourcePath("settings", ".js"));
|
||||||
};
|
};
|
||||||
|
|
||||||
window.searchState = {
|
window.searchState = {
|
||||||
|
@ -304,8 +296,8 @@ function loadCss(cssFileName) {
|
||||||
function loadSearch() {
|
function loadSearch() {
|
||||||
if (!searchLoaded) {
|
if (!searchLoaded) {
|
||||||
searchLoaded = true;
|
searchLoaded = true;
|
||||||
loadScript(window.searchJS);
|
loadScript(resourcePath("search", ".js"));
|
||||||
loadScript(window.searchIndexJS);
|
loadScript(resourcePath("search-index", ".js"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,40 +477,11 @@ function loadCss(cssFileName) {
|
||||||
document.addEventListener("keypress", handleShortcut);
|
document.addEventListener("keypress", handleShortcut);
|
||||||
document.addEventListener("keydown", handleShortcut);
|
document.addEventListener("keydown", handleShortcut);
|
||||||
|
|
||||||
// delayed sidebar rendering.
|
function addSidebarItems() {
|
||||||
window.initSidebarItems = items => {
|
if (!window.SIDEBAR_ITEMS) {
|
||||||
const sidebar = document.getElementsByClassName("sidebar-elems")[0];
|
|
||||||
let others;
|
|
||||||
const current = window.sidebarCurrent;
|
|
||||||
|
|
||||||
function addSidebarCrates(crates) {
|
|
||||||
if (!hasClass(document.body, "crate")) {
|
|
||||||
// We only want to list crates on the crate page.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Draw a convenient sidebar of known crates if we have a listing
|
const sidebar = document.getElementsByClassName("sidebar-elems")[0];
|
||||||
const div = document.createElement("div");
|
|
||||||
div.className = "block crate";
|
|
||||||
div.innerHTML = "<h3>Crates</h3>";
|
|
||||||
const ul = document.createElement("ul");
|
|
||||||
div.appendChild(ul);
|
|
||||||
|
|
||||||
for (const crate of crates) {
|
|
||||||
let klass = "crate";
|
|
||||||
if (window.rootPath !== "./" && crate === window.currentCrate) {
|
|
||||||
klass += " current";
|
|
||||||
}
|
|
||||||
const link = document.createElement("a");
|
|
||||||
link.href = window.rootPath + crate + "/index.html";
|
|
||||||
link.className = klass;
|
|
||||||
link.textContent = crate;
|
|
||||||
|
|
||||||
const li = document.createElement("li");
|
|
||||||
li.appendChild(link);
|
|
||||||
ul.appendChild(li);
|
|
||||||
}
|
|
||||||
others.appendChild(div);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
|
* Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items.
|
||||||
|
@ -529,7 +492,7 @@ function loadCss(cssFileName) {
|
||||||
* "Modules", or "Macros".
|
* "Modules", or "Macros".
|
||||||
*/
|
*/
|
||||||
function block(shortty, id, longty) {
|
function block(shortty, id, longty) {
|
||||||
const filtered = items[shortty];
|
const filtered = window.SIDEBAR_ITEMS[shortty];
|
||||||
if (!filtered) {
|
if (!filtered) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -546,17 +509,18 @@ function loadCss(cssFileName) {
|
||||||
const desc = item[1]; // can be null
|
const desc = item[1]; // can be null
|
||||||
|
|
||||||
let klass = shortty;
|
let klass = shortty;
|
||||||
if (name === current.name && shortty === current.ty) {
|
|
||||||
klass += " current";
|
|
||||||
}
|
|
||||||
let path;
|
let path;
|
||||||
if (shortty === "mod") {
|
if (shortty === "mod") {
|
||||||
path = name + "/index.html";
|
path = name + "/index.html";
|
||||||
} else {
|
} else {
|
||||||
path = shortty + "." + name + ".html";
|
path = shortty + "." + name + ".html";
|
||||||
}
|
}
|
||||||
|
const current_page = document.location.href.split("/").pop();
|
||||||
|
if (path === current_page) {
|
||||||
|
klass += " current";
|
||||||
|
}
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.href = current.relpath + path;
|
link.href = path;
|
||||||
link.title = desc;
|
link.title = desc;
|
||||||
link.className = klass;
|
link.className = klass;
|
||||||
link.textContent = name;
|
link.textContent = name;
|
||||||
|
@ -565,14 +529,10 @@ function loadCss(cssFileName) {
|
||||||
ul.appendChild(li);
|
ul.appendChild(li);
|
||||||
}
|
}
|
||||||
div.appendChild(ul);
|
div.appendChild(ul);
|
||||||
others.appendChild(div);
|
sidebar.appendChild(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sidebar) {
|
if (sidebar) {
|
||||||
others = document.createElement("div");
|
|
||||||
others.className = "others";
|
|
||||||
sidebar.appendChild(others);
|
|
||||||
|
|
||||||
const isModule = hasClass(document.body, "mod");
|
const isModule = hasClass(document.body, "mod");
|
||||||
if (!isModule) {
|
if (!isModule) {
|
||||||
block("primitive", "primitives", "Primitive Types");
|
block("primitive", "primitives", "Primitive Types");
|
||||||
|
@ -590,12 +550,8 @@ function loadCss(cssFileName) {
|
||||||
block("keyword", "keywords", "Keywords");
|
block("keyword", "keywords", "Keywords");
|
||||||
block("traitalias", "trait-aliases", "Trait Aliases");
|
block("traitalias", "trait-aliases", "Trait Aliases");
|
||||||
}
|
}
|
||||||
|
|
||||||
// `crates{version}.js` should always be loaded before this script, so we can use
|
|
||||||
// it safely.
|
|
||||||
addSidebarCrates(window.ALL_CRATES);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
window.register_implementors = imp => {
|
window.register_implementors = imp => {
|
||||||
const implementors = document.getElementById("implementors-list");
|
const implementors = document.getElementById("implementors-list");
|
||||||
|
@ -680,6 +636,39 @@ function loadCss(cssFileName) {
|
||||||
window.register_implementors(window.pending_implementors);
|
window.register_implementors(window.pending_implementors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addSidebarCrates() {
|
||||||
|
if (!window.ALL_CRATES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sidebarElems = document.getElementsByClassName("sidebar-elems")[0];
|
||||||
|
if (!sidebarElems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Draw a convenient sidebar of known crates if we have a listing
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.className = "block crate";
|
||||||
|
div.innerHTML = "<h3>Crates</h3>";
|
||||||
|
const ul = document.createElement("ul");
|
||||||
|
div.appendChild(ul);
|
||||||
|
|
||||||
|
for (const crate of window.ALL_CRATES) {
|
||||||
|
let klass = "crate";
|
||||||
|
if (window.rootPath !== "./" && crate === window.currentCrate) {
|
||||||
|
klass += " current";
|
||||||
|
}
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = window.rootPath + crate + "/index.html";
|
||||||
|
link.className = klass;
|
||||||
|
link.textContent = crate;
|
||||||
|
|
||||||
|
const li = document.createElement("li");
|
||||||
|
li.appendChild(link);
|
||||||
|
ul.appendChild(li);
|
||||||
|
}
|
||||||
|
sidebarElems.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function labelForToggleButton(sectionIsCollapsed) {
|
function labelForToggleButton(sectionIsCollapsed) {
|
||||||
if (sectionIsCollapsed) {
|
if (sectionIsCollapsed) {
|
||||||
// button will expand the section
|
// button will expand the section
|
||||||
|
@ -924,6 +913,9 @@ function loadCss(cssFileName) {
|
||||||
buildHelperPopup = () => {};
|
buildHelperPopup = () => {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setMobileTopbar();
|
||||||
|
addSidebarItems();
|
||||||
|
addSidebarCrates();
|
||||||
onHashChange(null);
|
onHashChange(null);
|
||||||
window.addEventListener("hashchange", onHashChange);
|
window.addEventListener("hashchange", onHashChange);
|
||||||
searchState.setup();
|
searchState.setup();
|
||||||
|
|
|
@ -1719,10 +1719,11 @@ function initSearch(rawSearchIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let crates = "";
|
let crates = "";
|
||||||
if (window.ALL_CRATES.length > 1) {
|
const crates_list = Object.keys(rawSearchIndex);
|
||||||
|
if (crates_list.length > 1) {
|
||||||
crates = " in <select id=\"crate-search\"><option value=\"All crates\">" +
|
crates = " in <select id=\"crate-search\"><option value=\"All crates\">" +
|
||||||
"All crates</option>";
|
"All crates</option>";
|
||||||
for (const c of window.ALL_CRATES) {
|
for (const c of crates_list) {
|
||||||
crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
|
crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`;
|
||||||
}
|
}
|
||||||
crates += "</select>";
|
crates += "</select>";
|
||||||
|
|
|
@ -9,33 +9,19 @@
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
function getCurrentFilePath() {
|
const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
|
||||||
const parts = window.location.pathname.split("/");
|
|
||||||
const rootPathParts = window.rootPath.split("/");
|
|
||||||
|
|
||||||
for (const rootPathPart of rootPathParts) {
|
function createDirEntry(elem, parent, fullPath, hasFoundFile) {
|
||||||
if (rootPathPart === "..") {
|
|
||||||
parts.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let file = window.location.pathname.substring(parts.join("/").length);
|
|
||||||
if (file.startsWith("/")) {
|
|
||||||
file = file.substring(1);
|
|
||||||
}
|
|
||||||
return file.substring(0, file.length - 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
|
|
||||||
const name = document.createElement("div");
|
const name = document.createElement("div");
|
||||||
name.className = "name";
|
name.className = "name";
|
||||||
|
|
||||||
fullPath += elem["name"] + "/";
|
fullPath += elem["name"] + "/";
|
||||||
|
|
||||||
name.onclick = () => {
|
name.onclick = ev => {
|
||||||
if (hasClass(name, "expand")) {
|
if (hasClass(ev.target, "expand")) {
|
||||||
removeClass(name, "expand");
|
removeClass(ev.target, "expand");
|
||||||
} else {
|
} else {
|
||||||
addClass(name, "expand");
|
addClass(ev.target, "expand");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
name.innerText = elem["name"];
|
name.innerText = elem["name"];
|
||||||
|
@ -46,7 +32,7 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
|
||||||
folders.className = "folders";
|
folders.className = "folders";
|
||||||
if (elem.dirs) {
|
if (elem.dirs) {
|
||||||
for (const dir of elem.dirs) {
|
for (const dir of elem.dirs) {
|
||||||
if (createDirEntry(dir, folders, fullPath, currentFile, hasFoundFile)) {
|
if (createDirEntry(dir, folders, fullPath, hasFoundFile)) {
|
||||||
addClass(name, "expand");
|
addClass(name, "expand");
|
||||||
hasFoundFile = true;
|
hasFoundFile = true;
|
||||||
}
|
}
|
||||||
|
@ -60,8 +46,9 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
|
||||||
for (const file_text of elem.files) {
|
for (const file_text of elem.files) {
|
||||||
const file = document.createElement("a");
|
const file = document.createElement("a");
|
||||||
file.innerText = file_text;
|
file.innerText = file_text;
|
||||||
file.href = window.rootPath + "src/" + fullPath + file_text + ".html";
|
file.href = rootPath + "src/" + fullPath + file_text + ".html";
|
||||||
if (!hasFoundFile && currentFile === fullPath + file_text) {
|
const w = window.location.href.split("#")[0];
|
||||||
|
if (!hasFoundFile && w === file.href) {
|
||||||
file.className = "selected";
|
file.className = "selected";
|
||||||
addClass(name, "expand");
|
addClass(name, "expand");
|
||||||
hasFoundFile = true;
|
hasFoundFile = true;
|
||||||
|
@ -72,7 +59,7 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
|
||||||
children.appendChild(files);
|
children.appendChild(files);
|
||||||
parent.appendChild(name);
|
parent.appendChild(name);
|
||||||
parent.appendChild(children);
|
parent.appendChild(children);
|
||||||
return hasFoundFile && currentFile.startsWith(fullPath);
|
return hasFoundFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSidebar() {
|
function toggleSidebar() {
|
||||||
|
@ -109,9 +96,6 @@ function createSidebarToggle() {
|
||||||
// This function is called from "source-files.js", generated in `html/render/mod.rs`.
|
// This function is called from "source-files.js", generated in `html/render/mod.rs`.
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function createSourceSidebar() {
|
function createSourceSidebar() {
|
||||||
if (!window.rootPath.endsWith("/")) {
|
|
||||||
window.rootPath += "/";
|
|
||||||
}
|
|
||||||
const container = document.querySelector("nav.sidebar");
|
const container = document.querySelector("nav.sidebar");
|
||||||
|
|
||||||
const sidebarToggle = createSidebarToggle();
|
const sidebarToggle = createSidebarToggle();
|
||||||
|
@ -125,7 +109,6 @@ function createSourceSidebar() {
|
||||||
container.classList.add("expanded");
|
container.classList.add("expanded");
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentFile = getCurrentFilePath();
|
|
||||||
let hasFoundFile = false;
|
let hasFoundFile = false;
|
||||||
|
|
||||||
const title = document.createElement("div");
|
const title = document.createElement("div");
|
||||||
|
@ -135,7 +118,7 @@ function createSourceSidebar() {
|
||||||
Object.keys(sourcesIndex).forEach(key => {
|
Object.keys(sourcesIndex).forEach(key => {
|
||||||
sourcesIndex[key].name = key;
|
sourcesIndex[key].name = key;
|
||||||
hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
|
hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
|
||||||
currentFile, hasFoundFile);
|
hasFoundFile);
|
||||||
});
|
});
|
||||||
|
|
||||||
container.appendChild(sidebar);
|
container.appendChild(sidebar);
|
||||||
|
|
|
@ -34,17 +34,18 @@
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
></script> {#- -#}
|
></script> {#- -#}
|
||||||
<script src="{{static_root_path|safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
|
<script src="{{static_root_path|safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
<script src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
|
{%- if page.css_class.contains("crate") -%}
|
||||||
|
<script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
|
{%- else if page.css_class == "source" -%}
|
||||||
|
<script defer src="{{static_root_path|safe}}source-script{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
|
<script defer src="{{page.root_path|safe}}source-files{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
|
{%- else -%}
|
||||||
|
<script defer src="sidebar-items{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
|
{%- endif -%}
|
||||||
<script defer src="{{static_root_path|safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
|
<script defer src="{{static_root_path|safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
{%- for script in page.static_extra_scripts -%}
|
|
||||||
<script defer src="{{static_root_path|safe}}{{script}}.js"></script> {#- -#}
|
|
||||||
{% endfor %}
|
|
||||||
{%- if layout.scrape_examples_extension -%}
|
{%- if layout.scrape_examples_extension -%}
|
||||||
<script defer src="{{page.root_path|safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
|
<script defer src="{{page.root_path|safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- for script in page.extra_scripts -%}
|
|
||||||
<script defer src="{{page.root_path|safe}}{{script}}.js"></script> {#- -#}
|
|
||||||
{% endfor %}
|
|
||||||
<noscript> {#- -#}
|
<noscript> {#- -#}
|
||||||
<link rel="stylesheet" {# -#}
|
<link rel="stylesheet" {# -#}
|
||||||
href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
|
href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// This test ensures that there is no macro duplicates in the sidebar.
|
// This test ensures that there is no macro duplicates in the sidebar.
|
||||||
goto: file://|DOC_PATH|/test_docs/macro.a.html
|
goto: file://|DOC_PATH|/test_docs/macro.a.html
|
||||||
// Waiting for the elements in the sidebar to be rendered.
|
// Waiting for the elements in the sidebar to be rendered.
|
||||||
wait-for: ".sidebar-elems .others .macro"
|
wait-for: ".sidebar-elems .macro"
|
||||||
// Check there is only one macro named "a" listed in the sidebar.
|
// Check there is only one macro named "a" listed in the sidebar.
|
||||||
assert-count: (
|
assert-count: (
|
||||||
"//*[@class='sidebar-elems']//*[@class='others']/*[@class='block macro']//li/a[text()='a']",
|
"//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='a']",
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
// Check there is only one macro named "b" listed in the sidebar.
|
// Check there is only one macro named "b" listed in the sidebar.
|
||||||
assert-count: (
|
assert-count: (
|
||||||
"//*[@class='sidebar-elems']//*[@class='others']/*[@class='block macro']//li/a[text()='b']",
|
"//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='b']",
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
|
|
@ -106,8 +106,8 @@ assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0
|
||||||
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "14px"})
|
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "14px"})
|
||||||
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
|
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
|
||||||
|
|
||||||
assert-text: (".sidebar .others h3", "Modules")
|
assert-text: (".sidebar .mod h3", "Modules")
|
||||||
assert-css: (".sidebar .others h3", {"border-bottom-width": "0px"}, ALL)
|
assert-css: (".sidebar .mod h3", {"border-bottom-width": "0px"}, ALL)
|
||||||
|
|
||||||
goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
|
goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error: implementation of `Foo` is not general enough
|
||||||
--> $DIR/hrtb-just-for-static.rs:24:5
|
--> $DIR/hrtb-just-for-static.rs:24:5
|
||||||
|
|
|
|
||||||
LL | want_hrtb::<StaticInt>()
|
LL | want_hrtb::<StaticInt>()
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
| ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||||
|
|
|
|
||||||
= note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
|
= note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
|
||||||
= note: ...but it actually implements `Foo<&'static isize>`
|
= note: ...but it actually implements `Foo<&'static isize>`
|
||||||
|
|
18
src/test/ui/issues/issue-98299.rs
Normal file
18
src/test/ui/issues/issue-98299.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
pub fn test_usage(p: ()) {
|
||||||
|
SmallCString::try_from(p).map(|cstr| cstr);
|
||||||
|
//~^ ERROR: type annotations needed
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SmallCString<const N: usize> {}
|
||||||
|
|
||||||
|
impl<const N: usize> TryFrom<()> for SmallCString<N> {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(path: ()) -> Result<Self, Self::Error> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
9
src/test/ui/issues/issue-98299.stderr
Normal file
9
src/test/ui/issues/issue-98299.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/issue-98299.rs:4:5
|
||||||
|
|
|
||||||
|
LL | SmallCString::try_from(p).map(|cstr| cstr);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for enum `Result<SmallCString<{_: usize}>, ()>`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
16
src/test/ui/nll/issue-97997.rs
Normal file
16
src/test/ui/nll/issue-97997.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
trait Foo {
|
||||||
|
const ASSOC: bool = true;
|
||||||
|
}
|
||||||
|
impl<T> Foo for fn(T) {}
|
||||||
|
|
||||||
|
fn foo(_x: i32) {}
|
||||||
|
|
||||||
|
fn impls_foo<T: Foo>(_x: T) {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
impls_foo(foo as fn(i32));
|
||||||
|
|
||||||
|
<fn(&u8) as Foo>::ASSOC;
|
||||||
|
//~^ ERROR implementation of `Foo` is not general enough
|
||||||
|
//~| ERROR implementation of `Foo` is not general enough
|
||||||
|
}
|
20
src/test/ui/nll/issue-97997.stderr
Normal file
20
src/test/ui/nll/issue-97997.stderr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
error: implementation of `Foo` is not general enough
|
||||||
|
--> $DIR/issue-97997.rs:13:5
|
||||||
|
|
|
||||||
|
LL | <fn(&u8) as Foo>::ASSOC;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||||
|
|
|
||||||
|
= note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)`
|
||||||
|
= note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`
|
||||||
|
|
||||||
|
error: implementation of `Foo` is not general enough
|
||||||
|
--> $DIR/issue-97997.rs:13:5
|
||||||
|
|
|
||||||
|
LL | <fn(&u8) as Foo>::ASSOC;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||||
|
|
|
||||||
|
= note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)`
|
||||||
|
= note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 366bd7242ed00c65f293497a26eb81c7510ac682
|
Subproject commit 427061da19723f2206fe4dcb175c9c43b9a6193d
|
Loading…
Add table
Add a link
Reference in a new issue