Auto merge of #134959 - jhpratt:rollup-vxt40of, r=jhpratt

Rollup of 3 pull requests

Successful merges:

 - #134291 (Use python built in type annotations in LLDB visualizer scripts)
 - #134857 (Unsafe binder support in rustdoc)
 - #134957 (chore: fix some typos)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-12-31 10:36:06 +00:00
commit aea4e43703
14 changed files with 209 additions and 229 deletions

View file

@ -5,11 +5,11 @@ from rust_types import RustType, classify_struct, classify_union
# BACKCOMPAT: rust 1.35 # BACKCOMPAT: rust 1.35
def is_hashbrown_hashmap(hash_map): def is_hashbrown_hashmap(hash_map: lldb.SBValue) -> bool:
return len(hash_map.type.fields) == 1 return len(hash_map.type.fields) == 1
def classify_rust_type(type): def classify_rust_type(type: lldb.SBType) -> str:
type_class = type.GetTypeClass() type_class = type.GetTypeClass()
if type_class == lldb.eTypeClassStruct: if type_class == lldb.eTypeClassStruct:
return classify_struct(type.name, type.fields) return classify_struct(type.name, type.fields)
@ -19,106 +19,104 @@ def classify_rust_type(type):
return RustType.OTHER return RustType.OTHER
def summary_lookup(valobj, dict): def summary_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
"""Returns the summary provider for the given value""" """Returns the summary provider for the given value"""
rust_type = classify_rust_type(valobj.GetType()) rust_type = classify_rust_type(valobj.GetType())
if rust_type == RustType.STD_STRING: if rust_type == RustType.STD_STRING:
return StdStringSummaryProvider(valobj, dict) return StdStringSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_OS_STRING: if rust_type == RustType.STD_OS_STRING:
return StdOsStringSummaryProvider(valobj, dict) return StdOsStringSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_STR: if rust_type == RustType.STD_STR:
return StdStrSummaryProvider(valobj, dict) return StdStrSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_VEC: if rust_type == RustType.STD_VEC:
return SizeSummaryProvider(valobj, dict) return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_VEC_DEQUE: if rust_type == RustType.STD_VEC_DEQUE:
return SizeSummaryProvider(valobj, dict) return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_SLICE: if rust_type == RustType.STD_SLICE:
return SizeSummaryProvider(valobj, dict) return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_HASH_MAP: if rust_type == RustType.STD_HASH_MAP:
return SizeSummaryProvider(valobj, dict) return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_HASH_SET: if rust_type == RustType.STD_HASH_SET:
return SizeSummaryProvider(valobj, dict) return SizeSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_RC: if rust_type == RustType.STD_RC:
return StdRcSummaryProvider(valobj, dict) return StdRcSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_ARC: if rust_type == RustType.STD_ARC:
return StdRcSummaryProvider(valobj, dict) return StdRcSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_REF: if rust_type == RustType.STD_REF:
return StdRefSummaryProvider(valobj, dict) return StdRefSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_REF_MUT: if rust_type == RustType.STD_REF_MUT:
return StdRefSummaryProvider(valobj, dict) return StdRefSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_REF_CELL: if rust_type == RustType.STD_REF_CELL:
return StdRefSummaryProvider(valobj, dict) return StdRefSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_NONZERO_NUMBER: if rust_type == RustType.STD_NONZERO_NUMBER:
return StdNonZeroNumberSummaryProvider(valobj, dict) return StdNonZeroNumberSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_PATHBUF: if rust_type == RustType.STD_PATHBUF:
return StdPathBufSummaryProvider(valobj, dict) return StdPathBufSummaryProvider(valobj, _dict)
if rust_type == RustType.STD_PATH: if rust_type == RustType.STD_PATH:
return StdPathSummaryProvider(valobj, dict) return StdPathSummaryProvider(valobj, _dict)
return "" return ""
def synthetic_lookup(valobj, dict): def synthetic_lookup(valobj: lldb.SBValue, _dict: LLDBOpaque) -> object:
# type: (SBValue, dict) -> object
"""Returns the synthetic provider for the given value""" """Returns the synthetic provider for the given value"""
rust_type = classify_rust_type(valobj.GetType()) rust_type = classify_rust_type(valobj.GetType())
if rust_type == RustType.STRUCT: if rust_type == RustType.STRUCT:
return StructSyntheticProvider(valobj, dict) return StructSyntheticProvider(valobj, _dict)
if rust_type == RustType.STRUCT_VARIANT: if rust_type == RustType.STRUCT_VARIANT:
return StructSyntheticProvider(valobj, dict, is_variant=True) return StructSyntheticProvider(valobj, _dict, is_variant=True)
if rust_type == RustType.TUPLE: if rust_type == RustType.TUPLE:
return TupleSyntheticProvider(valobj, dict) return TupleSyntheticProvider(valobj, _dict)
if rust_type == RustType.TUPLE_VARIANT: if rust_type == RustType.TUPLE_VARIANT:
return TupleSyntheticProvider(valobj, dict, is_variant=True) return TupleSyntheticProvider(valobj, _dict, is_variant=True)
if rust_type == RustType.EMPTY: if rust_type == RustType.EMPTY:
return EmptySyntheticProvider(valobj, dict) return EmptySyntheticProvider(valobj, _dict)
if rust_type == RustType.REGULAR_ENUM: if rust_type == RustType.REGULAR_ENUM:
discriminant = valobj.GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned() discriminant = valobj.GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned()
return synthetic_lookup(valobj.GetChildAtIndex(discriminant), dict) return synthetic_lookup(valobj.GetChildAtIndex(discriminant), _dict)
if rust_type == RustType.SINGLETON_ENUM: if rust_type == RustType.SINGLETON_ENUM:
return synthetic_lookup(valobj.GetChildAtIndex(0), dict) return synthetic_lookup(valobj.GetChildAtIndex(0), _dict)
if rust_type == RustType.ENUM: if rust_type == RustType.ENUM:
return ClangEncodedEnumProvider(valobj, dict) return ClangEncodedEnumProvider(valobj, _dict)
if rust_type == RustType.STD_VEC: if rust_type == RustType.STD_VEC:
return StdVecSyntheticProvider(valobj, dict) return StdVecSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_VEC_DEQUE: if rust_type == RustType.STD_VEC_DEQUE:
return StdVecDequeSyntheticProvider(valobj, dict) return StdVecDequeSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_SLICE or rust_type == RustType.STD_STR: if rust_type == RustType.STD_SLICE or rust_type == RustType.STD_STR:
return StdSliceSyntheticProvider(valobj, dict) return StdSliceSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_HASH_MAP: if rust_type == RustType.STD_HASH_MAP:
if is_hashbrown_hashmap(valobj): if is_hashbrown_hashmap(valobj):
return StdHashMapSyntheticProvider(valobj, dict) return StdHashMapSyntheticProvider(valobj, _dict)
else: else:
return StdOldHashMapSyntheticProvider(valobj, dict) return StdOldHashMapSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_HASH_SET: if rust_type == RustType.STD_HASH_SET:
hash_map = valobj.GetChildAtIndex(0) hash_map = valobj.GetChildAtIndex(0)
if is_hashbrown_hashmap(hash_map): if is_hashbrown_hashmap(hash_map):
return StdHashMapSyntheticProvider(valobj, dict, show_values=False) return StdHashMapSyntheticProvider(valobj, _dict, show_values=False)
else: else:
return StdOldHashMapSyntheticProvider(hash_map, dict, show_values=False) return StdOldHashMapSyntheticProvider(hash_map, _dict, show_values=False)
if rust_type == RustType.STD_RC: if rust_type == RustType.STD_RC:
return StdRcSyntheticProvider(valobj, dict) return StdRcSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_ARC: if rust_type == RustType.STD_ARC:
return StdRcSyntheticProvider(valobj, dict, is_atomic=True) return StdRcSyntheticProvider(valobj, _dict, is_atomic=True)
if rust_type == RustType.STD_CELL: if rust_type == RustType.STD_CELL:
return StdCellSyntheticProvider(valobj, dict) return StdCellSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_REF: if rust_type == RustType.STD_REF:
return StdRefSyntheticProvider(valobj, dict) return StdRefSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_REF_MUT: if rust_type == RustType.STD_REF_MUT:
return StdRefSyntheticProvider(valobj, dict) return StdRefSyntheticProvider(valobj, _dict)
if rust_type == RustType.STD_REF_CELL: if rust_type == RustType.STD_REF_CELL:
return StdRefSyntheticProvider(valobj, dict, is_cell=True) return StdRefSyntheticProvider(valobj, _dict, is_cell=True)
return DefaultSyntheticProvider(valobj, dict) return DefaultSyntheticProvider(valobj, _dict)

View file

@ -3,6 +3,7 @@ import sys
from lldb import ( from lldb import (
SBData, SBData,
SBError, SBError,
SBValue,
eBasicTypeLong, eBasicTypeLong,
eBasicTypeUnsignedLong, eBasicTypeUnsignedLong,
eBasicTypeUnsignedChar, eBasicTypeUnsignedChar,
@ -44,24 +45,28 @@ from lldb import (
PY3 = sys.version_info[0] == 3 PY3 = sys.version_info[0] == 3
class LLDBOpaque:
"""
An marker type for use in type hints to denote LLDB bookkeeping variables. Values marked with
this type should never be used except when passing as an argument to an LLDB function.
"""
class ValueBuilder: class ValueBuilder:
def __init__(self, valobj): def __init__(self, valobj: SBValue):
# type: (SBValue) -> ValueBuilder
self.valobj = valobj self.valobj = valobj
process = valobj.GetProcess() process = valobj.GetProcess()
self.endianness = process.GetByteOrder() self.endianness = process.GetByteOrder()
self.pointer_size = process.GetAddressByteSize() self.pointer_size = process.GetAddressByteSize()
def from_int(self, name, value): def from_int(self, name: str, value: int) -> SBValue:
# type: (str, int) -> SBValue
type = self.valobj.GetType().GetBasicType(eBasicTypeLong) type = self.valobj.GetType().GetBasicType(eBasicTypeLong)
data = SBData.CreateDataFromSInt64Array( data = SBData.CreateDataFromSInt64Array(
self.endianness, self.pointer_size, [value] self.endianness, self.pointer_size, [value]
) )
return self.valobj.CreateValueFromData(name, data, type) return self.valobj.CreateValueFromData(name, data, type)
def from_uint(self, name, value): def from_uint(self, name: str, value: int) -> SBValue:
# type: (str, int) -> SBValue
type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong) type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)
data = SBData.CreateDataFromUInt64Array( data = SBData.CreateDataFromUInt64Array(
self.endianness, self.pointer_size, [value] self.endianness, self.pointer_size, [value]
@ -69,7 +74,7 @@ class ValueBuilder:
return self.valobj.CreateValueFromData(name, data, type) return self.valobj.CreateValueFromData(name, data, type)
def unwrap_unique_or_non_null(unique_or_nonnull): def unwrap_unique_or_non_null(unique_or_nonnull: SBValue) -> SBValue:
# BACKCOMPAT: rust 1.32 # BACKCOMPAT: rust 1.32
# https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067 # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
# BACKCOMPAT: rust 1.60 # BACKCOMPAT: rust 1.60
@ -79,67 +84,54 @@ def unwrap_unique_or_non_null(unique_or_nonnull):
class DefaultSyntheticProvider: class DefaultSyntheticProvider:
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
# type: (SBValue, dict) -> DefaultSyntheticProvider
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "Default synthetic provider for " + str(valobj.GetName()) # logger >> "Default synthetic provider for " + str(valobj.GetName())
self.valobj = valobj self.valobj = valobj
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.valobj.GetNumChildren() return self.valobj.GetNumChildren()
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
return self.valobj.GetIndexOfChildWithName(name) return self.valobj.GetIndexOfChildWithName(name)
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
return self.valobj.GetChildAtIndex(index) return self.valobj.GetChildAtIndex(index)
def update(self): def update(self):
# type: () -> None
pass pass
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return self.valobj.MightHaveChildren() return self.valobj.MightHaveChildren()
class EmptySyntheticProvider: class EmptySyntheticProvider:
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
# type: (SBValue, dict) -> EmptySyntheticProvider
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[EmptySyntheticProvider] for " + str(valobj.GetName()) # logger >> "[EmptySyntheticProvider] for " + str(valobj.GetName())
self.valobj = valobj self.valobj = valobj
def num_children(self): def num_children(self) -> int:
# type: () -> int
return 0 return 0
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int return -1
return None
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
return None return None
def update(self): def update(self):
# type: () -> None
pass pass
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return False return False
def SizeSummaryProvider(valobj, dict): def SizeSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
return "size=" + str(valobj.GetNumChildren()) return "size=" + str(valobj.GetNumChildren())
def vec_to_string(vec): def vec_to_string(vec: SBValue) -> str:
length = vec.GetNumChildren() length = vec.GetNumChildren()
chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)] chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)]
return ( return (
@ -149,16 +141,14 @@ def vec_to_string(vec):
) )
def StdStringSummaryProvider(valobj, dict): def StdStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName()) # logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName())
vec = valobj.GetChildAtIndex(0) vec = valobj.GetChildAtIndex(0)
return '"%s"' % vec_to_string(vec) return '"%s"' % vec_to_string(vec)
def StdOsStringSummaryProvider(valobj, dict): def StdOsStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdOsStringSummaryProvider] for " + str(valobj.GetName()) # logger >> "[StdOsStringSummaryProvider] for " + str(valobj.GetName())
buf = valobj.GetChildAtIndex(0).GetChildAtIndex(0) buf = valobj.GetChildAtIndex(0).GetChildAtIndex(0)
@ -167,8 +157,7 @@ def StdOsStringSummaryProvider(valobj, dict):
return '"%s"' % vec_to_string(vec) return '"%s"' % vec_to_string(vec)
def StdStrSummaryProvider(valobj, dict): def StdStrSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName()) # logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName())
@ -189,15 +178,13 @@ def StdStrSummaryProvider(valobj, dict):
return '"%s"' % data return '"%s"' % data
def StdPathBufSummaryProvider(valobj, dict): def StdPathBufSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdPathBufSummaryProvider] for " + str(valobj.GetName()) # logger >> "[StdPathBufSummaryProvider] for " + str(valobj.GetName())
return StdOsStringSummaryProvider(valobj.GetChildMemberWithName("inner"), dict) return StdOsStringSummaryProvider(valobj.GetChildMemberWithName("inner"), _dict)
def StdPathSummaryProvider(valobj, dict): def StdPathSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdPathSummaryProvider] for " + str(valobj.GetName()) # logger >> "[StdPathSummaryProvider] for " + str(valobj.GetName())
length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned() length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned()
@ -221,8 +208,7 @@ def StdPathSummaryProvider(valobj, dict):
class StructSyntheticProvider: class StructSyntheticProvider:
"""Pretty-printer for structs and struct enum variants""" """Pretty-printer for structs and struct enum variants"""
def __init__(self, valobj, dict, is_variant=False): def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_variant: bool = False):
# type: (SBValue, dict, bool) -> StructSyntheticProvider
# logger = Logger.Logger() # logger = Logger.Logger()
self.valobj = valobj self.valobj = valobj
self.is_variant = is_variant self.is_variant = is_variant
@ -239,16 +225,13 @@ class StructSyntheticProvider:
for number, field in enumerate(real_fields): for number, field in enumerate(real_fields):
self.fields[field.name] = number self.fields[field.name] = number
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.fields_count return self.fields_count
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
return self.fields.get(name, -1) return self.fields.get(name, -1)
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
if self.is_variant: if self.is_variant:
field = self.type.GetFieldAtIndex(index + 1) field = self.type.GetFieldAtIndex(index + 1)
else: else:
@ -259,8 +242,7 @@ class StructSyntheticProvider:
# type: () -> None # type: () -> None
pass pass
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
@ -270,26 +252,26 @@ class ClangEncodedEnumProvider:
DISCRIMINANT_MEMBER_NAME = "$discr$" DISCRIMINANT_MEMBER_NAME = "$discr$"
VALUE_MEMBER_NAME = "value" VALUE_MEMBER_NAME = "value"
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
self.valobj = valobj self.valobj = valobj
self.update() self.update()
def has_children(self): def has_children(self) -> bool:
return True return True
def num_children(self): def num_children(self) -> int:
if self.is_default: if self.is_default:
return 1 return 1
return 2 return 2
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
if name == ClangEncodedEnumProvider.VALUE_MEMBER_NAME: if name == ClangEncodedEnumProvider.VALUE_MEMBER_NAME:
return 0 return 0
if name == ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME: if name == ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME:
return 1 return 1
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
if index == 0: if index == 0:
return self.variant.GetChildMemberWithName( return self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.VALUE_MEMBER_NAME ClangEncodedEnumProvider.VALUE_MEMBER_NAME
@ -310,7 +292,7 @@ class ClangEncodedEnumProvider:
== -1 == -1
) )
def _getCurrentVariantIndex(self, all_variants): def _getCurrentVariantIndex(self, all_variants: SBValue) -> int:
default_index = 0 default_index = 0
for i in range(all_variants.GetNumChildren()): for i in range(all_variants.GetNumChildren()):
variant = all_variants.GetChildAtIndex(i) variant = all_variants.GetChildAtIndex(i)
@ -329,8 +311,7 @@ class ClangEncodedEnumProvider:
class TupleSyntheticProvider: class TupleSyntheticProvider:
"""Pretty-printer for tuples and tuple enum variants""" """Pretty-printer for tuples and tuple enum variants"""
def __init__(self, valobj, dict, is_variant=False): def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_variant: bool = False):
# type: (SBValue, dict, bool) -> TupleSyntheticProvider
# logger = Logger.Logger() # logger = Logger.Logger()
self.valobj = valobj self.valobj = valobj
self.is_variant = is_variant self.is_variant = is_variant
@ -341,19 +322,16 @@ class TupleSyntheticProvider:
else: else:
self.size = self.type.GetNumberOfFields() self.size = self.type.GetNumberOfFields()
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.size return self.size
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
if name.isdigit(): if name.isdigit():
return int(name) return int(name)
else: else:
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
if self.is_variant: if self.is_variant:
field = self.type.GetFieldAtIndex(index + 1) field = self.type.GetFieldAtIndex(index + 1)
else: else:
@ -364,11 +342,9 @@ class TupleSyntheticProvider:
) )
def update(self): def update(self):
# type: () -> None
pass pass
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
@ -385,27 +361,23 @@ class StdVecSyntheticProvider:
struct NonNull<T> { pointer: *const T } struct NonNull<T> { pointer: *const T }
""" """
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
# type: (SBValue, dict) -> StdVecSyntheticProvider
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName()) # logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName())
self.valobj = valobj self.valobj = valobj
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.length return self.length
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
index = name.lstrip("[").rstrip("]") index = name.lstrip("[").rstrip("]")
if index.isdigit(): if index.isdigit():
return int(index) return int(index)
else: else:
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned() start = self.data_ptr.GetValueAsUnsigned()
address = start + index * self.element_type_size address = start + index * self.element_type_size
element = self.data_ptr.CreateValueFromAddress( element = self.data_ptr.CreateValueFromAddress(
@ -414,7 +386,6 @@ class StdVecSyntheticProvider:
return element return element
def update(self): def update(self):
# type: () -> None
self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName( self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(
"inner" "inner"
@ -427,30 +398,26 @@ class StdVecSyntheticProvider:
self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
self.element_type_size = self.element_type.GetByteSize() self.element_type_size = self.element_type.GetByteSize()
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
class StdSliceSyntheticProvider: class StdSliceSyntheticProvider:
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
self.valobj = valobj self.valobj = valobj
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.length return self.length
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
index = name.lstrip("[").rstrip("]") index = name.lstrip("[").rstrip("]")
if index.isdigit(): if index.isdigit():
return int(index) return int(index)
else: else:
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned() start = self.data_ptr.GetValueAsUnsigned()
address = start + index * self.element_type_size address = start + index * self.element_type_size
element = self.data_ptr.CreateValueFromAddress( element = self.data_ptr.CreateValueFromAddress(
@ -459,15 +426,13 @@ class StdSliceSyntheticProvider:
return element return element
def update(self): def update(self):
# type: () -> None
self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned() self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()
self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr") self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr")
self.element_type = self.data_ptr.GetType().GetPointeeType() self.element_type = self.data_ptr.GetType().GetPointeeType()
self.element_type_size = self.element_type.GetByteSize() self.element_type_size = self.element_type.GetByteSize()
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
@ -477,27 +442,23 @@ class StdVecDequeSyntheticProvider:
struct VecDeque<T> { head: usize, len: usize, buf: RawVec<T> } struct VecDeque<T> { head: usize, len: usize, buf: RawVec<T> }
""" """
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
# type: (SBValue, dict) -> StdVecDequeSyntheticProvider
# logger = Logger.Logger() # logger = Logger.Logger()
# logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName()) # logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName())
self.valobj = valobj self.valobj = valobj
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.size return self.size
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
index = name.lstrip("[").rstrip("]") index = name.lstrip("[").rstrip("]")
if index.isdigit() and int(index) < self.size: if index.isdigit() and int(index) < self.size:
return int(index) return int(index)
else: else:
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned() start = self.data_ptr.GetValueAsUnsigned()
address = start + ((index + self.head) % self.cap) * self.element_type_size address = start + ((index + self.head) % self.cap) * self.element_type_size
element = self.data_ptr.CreateValueFromAddress( element = self.data_ptr.CreateValueFromAddress(
@ -506,7 +467,6 @@ class StdVecDequeSyntheticProvider:
return element return element
def update(self): def update(self):
# type: () -> None
self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned() self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned()
self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName( self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(
@ -524,8 +484,7 @@ class StdVecDequeSyntheticProvider:
self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
self.element_type_size = self.element_type.GetByteSize() self.element_type_size = self.element_type.GetByteSize()
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
@ -537,26 +496,22 @@ class StdOldHashMapSyntheticProvider:
struct RawTable<K, V> { capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, ... } struct RawTable<K, V> { capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, ... }
""" """
def __init__(self, valobj, dict, show_values=True): def __init__(self, valobj: SBValue, _dict: LLDBOpaque, show_values: bool = True):
# type: (SBValue, dict, bool) -> StdOldHashMapSyntheticProvider
self.valobj = valobj self.valobj = valobj
self.show_values = show_values self.show_values = show_values
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.size return self.size
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
index = name.lstrip("[").rstrip("]") index = name.lstrip("[").rstrip("]")
if index.isdigit(): if index.isdigit():
return int(index) return int(index)
else: else:
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
# logger = Logger.Logger() # logger = Logger.Logger()
start = self.data_ptr.GetValueAsUnsigned() & ~1 start = self.data_ptr.GetValueAsUnsigned() & ~1
@ -592,7 +547,6 @@ class StdOldHashMapSyntheticProvider:
) )
def update(self): def update(self):
# type: () -> None
# logger = Logger.Logger() # logger = Logger.Logger()
self.table = self.valobj.GetChildMemberWithName("table") # type: SBValue self.table = self.valobj.GetChildMemberWithName("table") # type: SBValue
@ -624,34 +578,29 @@ class StdOldHashMapSyntheticProvider:
# logger >> "Valid indices: {}".format(str(self.valid_indices)) # logger >> "Valid indices: {}".format(str(self.valid_indices))
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
class StdHashMapSyntheticProvider: class StdHashMapSyntheticProvider:
"""Pretty-printer for hashbrown's HashMap""" """Pretty-printer for hashbrown's HashMap"""
def __init__(self, valobj, dict, show_values=True): def __init__(self, valobj: SBValue, _dict: LLDBOpaque, show_values: bool = True):
# type: (SBValue, dict, bool) -> StdHashMapSyntheticProvider
self.valobj = valobj self.valobj = valobj
self.show_values = show_values self.show_values = show_values
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
return self.size return self.size
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
index = name.lstrip("[").rstrip("]") index = name.lstrip("[").rstrip("]")
if index.isdigit(): if index.isdigit():
return int(index) return int(index)
else: else:
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
pairs_start = self.data_ptr.GetValueAsUnsigned() pairs_start = self.data_ptr.GetValueAsUnsigned()
idx = self.valid_indices[index] idx = self.valid_indices[index]
if self.new_layout: if self.new_layout:
@ -669,7 +618,6 @@ class StdHashMapSyntheticProvider:
) )
def update(self): def update(self):
# type: () -> None
table = self.table() table = self.table()
inner_table = table.GetChildMemberWithName("table") inner_table = table.GetChildMemberWithName("table")
@ -707,8 +655,7 @@ class StdHashMapSyntheticProvider:
if is_present: if is_present:
self.valid_indices.append(idx) self.valid_indices.append(idx)
def table(self): def table(self) -> SBValue:
# type: () -> SBValue
if self.show_values: if self.show_values:
hashbrown_hashmap = self.valobj.GetChildMemberWithName("base") hashbrown_hashmap = self.valobj.GetChildMemberWithName("base")
else: else:
@ -718,13 +665,11 @@ class StdHashMapSyntheticProvider:
hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0) hashbrown_hashmap = self.valobj.GetChildAtIndex(0).GetChildAtIndex(0)
return hashbrown_hashmap.GetChildMemberWithName("table") return hashbrown_hashmap.GetChildMemberWithName("table")
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
def StdRcSummaryProvider(valobj, dict): def StdRcSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned() strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned()
weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned() weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned()
return "strong={}, weak={}".format(strong, weak) return "strong={}, weak={}".format(strong, weak)
@ -746,8 +691,7 @@ class StdRcSyntheticProvider:
struct AtomicUsize { v: UnsafeCell<usize> } struct AtomicUsize { v: UnsafeCell<usize> }
""" """
def __init__(self, valobj, dict, is_atomic=False): def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_atomic: bool = False):
# type: (SBValue, dict, bool) -> StdRcSyntheticProvider
self.valobj = valobj self.valobj = valobj
self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr")) self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr"))
@ -769,13 +713,11 @@ class StdRcSyntheticProvider:
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
# Actually there are 3 children, but only the `value` should be shown as a child # Actually there are 3 children, but only the `value` should be shown as a child
return 1 return 1
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
if name == "value": if name == "value":
return 0 return 0
if name == "strong": if name == "strong":
@ -784,8 +726,7 @@ class StdRcSyntheticProvider:
return 2 return 2
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
if index == 0: if index == 0:
return self.value return self.value
if index == 1: if index == 1:
@ -796,50 +737,41 @@ class StdRcSyntheticProvider:
return None return None
def update(self): def update(self):
# type: () -> None
self.strong_count = self.strong.GetValueAsUnsigned() self.strong_count = self.strong.GetValueAsUnsigned()
self.weak_count = self.weak.GetValueAsUnsigned() - 1 self.weak_count = self.weak.GetValueAsUnsigned() - 1
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
class StdCellSyntheticProvider: class StdCellSyntheticProvider:
"""Pretty-printer for std::cell::Cell""" """Pretty-printer for std::cell::Cell"""
def __init__(self, valobj, dict): def __init__(self, valobj: SBValue, _dict: LLDBOpaque):
# type: (SBValue, dict) -> StdCellSyntheticProvider
self.valobj = valobj self.valobj = valobj
self.value = valobj.GetChildMemberWithName("value").GetChildAtIndex(0) self.value = valobj.GetChildMemberWithName("value").GetChildAtIndex(0)
def num_children(self): def num_children(self) -> int:
# type: () -> int
return 1 return 1
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
# type: (str) -> int
if name == "value": if name == "value":
return 0 return 0
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
if index == 0: if index == 0:
return self.value return self.value
return None return None
def update(self): def update(self):
# type: () -> None
pass pass
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
def StdRefSummaryProvider(valobj, dict): def StdRefSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned() borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()
return ( return (
"borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow) "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
@ -849,8 +781,7 @@ def StdRefSummaryProvider(valobj, dict):
class StdRefSyntheticProvider: class StdRefSyntheticProvider:
"""Pretty-printer for std::cell::Ref, std::cell::RefMut, and std::cell::RefCell""" """Pretty-printer for std::cell::Ref, std::cell::RefMut, and std::cell::RefCell"""
def __init__(self, valobj, dict, is_cell=False): def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_cell: bool = False):
# type: (SBValue, dict, bool) -> StdRefSyntheticProvider
self.valobj = valobj self.valobj = valobj
borrow = valobj.GetChildMemberWithName("borrow") borrow = valobj.GetChildMemberWithName("borrow")
@ -872,20 +803,18 @@ class StdRefSyntheticProvider:
self.update() self.update()
def num_children(self): def num_children(self) -> int:
# type: () -> int
# Actually there are 2 children, but only the `value` should be shown as a child # Actually there are 2 children, but only the `value` should be shown as a child
return 1 return 1
def get_child_index(self, name): def get_child_index(self, name: str) -> int:
if name == "value": if name == "value":
return 0 return 0
if name == "borrow": if name == "borrow":
return 1 return 1
return -1 return -1
def get_child_at_index(self, index): def get_child_at_index(self, index: int) -> SBValue:
# type: (int) -> SBValue
if index == 0: if index == 0:
return self.value return self.value
if index == 1: if index == 1:
@ -893,16 +822,13 @@ class StdRefSyntheticProvider:
return None return None
def update(self): def update(self):
# type: () -> None
self.borrow_count = self.borrow.GetValueAsSigned() self.borrow_count = self.borrow.GetValueAsSigned()
def has_children(self): def has_children(self) -> bool:
# type: () -> bool
return True return True
def StdNonZeroNumberSummaryProvider(valobj, _dict): def StdNonZeroNumberSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str:
# type: (SBValue, dict) -> str
inner = valobj.GetChildAtIndex(0) inner = valobj.GetChildAtIndex(0)
inner_inner = inner.GetChildAtIndex(0) inner_inner = inner.GetChildAtIndex(0)

View file

@ -1,3 +1,4 @@
from typing import List
import re import re
@ -85,12 +86,11 @@ STD_TYPE_TO_REGEX = {
} }
def is_tuple_fields(fields): def is_tuple_fields(fields: List) -> bool:
# type: (list) -> bool
return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields) return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields)
def classify_struct(name, fields): def classify_struct(name: str, fields: List) -> str:
if len(fields) == 0: if len(fields) == 0:
return RustType.EMPTY return RustType.EMPTY
@ -111,7 +111,7 @@ def classify_struct(name, fields):
return RustType.STRUCT return RustType.STRUCT
def classify_union(fields): def classify_union(fields: List) -> str:
if len(fields) == 0: if len(fields) == 0:
return RustType.EMPTY return RustType.EMPTY

View file

@ -1844,8 +1844,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
DynTrait(bounds, lifetime) DynTrait(bounds, lifetime)
} }
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
TyKind::UnsafeBinder(..) => { TyKind::UnsafeBinder(unsafe_binder_ty) => {
unimplemented!("unsafe binders are not supported yet") UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx)))
} }
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer TyKind::Infer
@ -2075,6 +2075,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
abi: sig.abi(), abi: sig.abi(),
})) }))
} }
ty::UnsafeBinder(inner) => {
let generic_params = clean_bound_vars(inner.bound_vars());
let ty = clean_middle_ty(inner.into(), cx, None, None);
UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, ty }))
}
ty::Adt(def, args) => { ty::Adt(def, args) => {
let did = def.did(); let did = def.did();
let kind = match def.adt_kind() { let kind = match def.adt_kind() {
@ -2253,7 +2258,6 @@ pub(crate) fn clean_middle_ty<'tcx>(
} }
} }
ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binders)"),
ty::Closure(..) => panic!("Closure"), ty::Closure(..) => panic!("Closure"),
ty::CoroutineClosure(..) => panic!("CoroutineClosure"), ty::CoroutineClosure(..) => panic!("CoroutineClosure"),
ty::Coroutine(..) => panic!("Coroutine"), ty::Coroutine(..) => panic!("Coroutine"),
@ -2564,6 +2568,21 @@ fn clean_bare_fn_ty<'tcx>(
BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params } BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params }
} }
fn clean_unsafe_binder_ty<'tcx>(
unsafe_binder_ty: &hir::UnsafeBinderTy<'tcx>,
cx: &mut DocContext<'tcx>,
) -> UnsafeBinderTy {
// NOTE: generics must be cleaned before args
let generic_params = unsafe_binder_ty
.generic_params
.iter()
.filter(|p| !is_elided_lifetime(p))
.map(|x| clean_generic_param(cx, None, x))
.collect();
let ty = clean_ty(unsafe_binder_ty.inner_ty, cx);
UnsafeBinderTy { generic_params, ty }
}
pub(crate) fn reexport_chain( pub(crate) fn reexport_chain(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
import_def_id: LocalDefId, import_def_id: LocalDefId,

View file

@ -32,7 +32,7 @@ use {rustc_ast as ast, rustc_hir as hir};
pub(crate) use self::ItemKind::*; pub(crate) use self::ItemKind::*;
pub(crate) use self::Type::{ pub(crate) use self::Type::{
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
RawPointer, SelfTy, Slice, Tuple, RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
}; };
use crate::clean::cfg::Cfg; use crate::clean::cfg::Cfg;
use crate::clean::clean_middle_path; use crate::clean::clean_middle_path;
@ -1511,6 +1511,8 @@ pub(crate) enum Type {
/// An `impl Trait`: `impl TraitA + TraitB + ...` /// An `impl Trait`: `impl TraitA + TraitB + ...`
ImplTrait(Vec<GenericBound>), ImplTrait(Vec<GenericBound>),
UnsafeBinder(Box<UnsafeBinderTy>),
} }
impl Type { impl Type {
@ -1703,7 +1705,7 @@ impl Type {
Type::Pat(..) => PrimitiveType::Pat, Type::Pat(..) => PrimitiveType::Pat,
RawPointer(..) => PrimitiveType::RawPointer, RawPointer(..) => PrimitiveType::RawPointer,
QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache), QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
Generic(_) | SelfTy | Infer | ImplTrait(_) => return None, Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
}; };
Primitive(t).def_id(cache) Primitive(t).def_id(cache)
} }
@ -2343,6 +2345,12 @@ pub(crate) struct BareFunctionDecl {
pub(crate) abi: ExternAbi, pub(crate) abi: ExternAbi,
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct UnsafeBinderTy {
pub(crate) generic_params: Vec<GenericParamDef>,
pub(crate) ty: Type,
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Static { pub(crate) struct Static {
pub(crate) type_: Box<Type>, pub(crate) type_: Box<Type>,

View file

@ -282,7 +282,8 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
match pred { match pred {
clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => { clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
print_higher_ranked_params_with_space(bound_params, cx).fmt(f)?; print_higher_ranked_params_with_space(bound_params, cx, "for")
.fmt(f)?;
ty.print(cx).fmt(f)?; ty.print(cx).fmt(f)?;
f.write_str(":")?; f.write_str(":")?;
if !bounds.is_empty() { if !bounds.is_empty() {
@ -386,7 +387,7 @@ impl clean::ConstantKind {
impl clean::PolyTrait { impl clean::PolyTrait {
fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> { fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
display_fn(move |f| { display_fn(move |f| {
print_higher_ranked_params_with_space(&self.generic_params, cx).fmt(f)?; print_higher_ranked_params_with_space(&self.generic_params, cx, "for").fmt(f)?;
self.trait_.print(cx).fmt(f) self.trait_.print(cx).fmt(f)
}) })
} }
@ -968,10 +969,12 @@ fn tybounds<'a, 'tcx: 'a>(
fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>( fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
params: &'a [clean::GenericParamDef], params: &'a [clean::GenericParamDef],
cx: &'a Context<'tcx>, cx: &'a Context<'tcx>,
keyword: &'static str,
) -> impl Display + 'a + Captures<'tcx> { ) -> impl Display + 'a + Captures<'tcx> {
display_fn(move |f| { display_fn(move |f| {
if !params.is_empty() { if !params.is_empty() {
f.write_str(if f.alternate() { "for<" } else { "for&lt;" })?; f.write_str(keyword)?;
f.write_str(if f.alternate() { "<" } else { "&lt;" })?;
comma_sep(params.iter().map(|lt| lt.print(cx)), true).fmt(f)?; comma_sep(params.iter().map(|lt| lt.print(cx)), true).fmt(f)?;
f.write_str(if f.alternate() { "> " } else { "&gt; " })?; f.write_str(if f.alternate() { "> " } else { "&gt; " })?;
} }
@ -1027,7 +1030,7 @@ fn fmt_type(
primitive_link(f, prim, format_args!("{}", prim.as_sym().as_str()), cx) primitive_link(f, prim, format_args!("{}", prim.as_sym().as_str()), cx)
} }
clean::BareFunction(ref decl) => { clean::BareFunction(ref decl) => {
print_higher_ranked_params_with_space(&decl.generic_params, cx).fmt(f)?; print_higher_ranked_params_with_space(&decl.generic_params, cx, "for").fmt(f)?;
decl.safety.print_with_space().fmt(f)?; decl.safety.print_with_space().fmt(f)?;
print_abi_with_space(decl.abi).fmt(f)?; print_abi_with_space(decl.abi).fmt(f)?;
if f.alternate() { if f.alternate() {
@ -1037,6 +1040,10 @@ fn fmt_type(
} }
decl.decl.print(cx).fmt(f) decl.decl.print(cx).fmt(f)
} }
clean::UnsafeBinder(ref binder) => {
print_higher_ranked_params_with_space(&binder.generic_params, cx, "unsafe").fmt(f)?;
binder.ty.print(cx).fmt(f)
}
clean::Tuple(ref typs) => match &typs[..] { clean::Tuple(ref typs) => match &typs[..] {
&[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx), &[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx),
[one] => { [one] => {
@ -1354,7 +1361,7 @@ impl clean::Impl {
// Hardcoded anchor library/core/src/primitive_docs.rs // Hardcoded anchor library/core/src/primitive_docs.rs
// Link should match `# Trait implementations` // Link should match `# Trait implementations`
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?; print_higher_ranked_params_with_space(&bare_fn.generic_params, cx, "for").fmt(f)?;
bare_fn.safety.print_with_space().fmt(f)?; bare_fn.safety.print_with_space().fmt(f)?;
print_abi_with_space(bare_fn.abi).fmt(f)?; print_abi_with_space(bare_fn.abi).fmt(f)?;
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };

View file

@ -900,7 +900,8 @@ fn get_index_type_id(
| clean::Generic(_) | clean::Generic(_)
| clean::SelfTy | clean::SelfTy
| clean::ImplTrait(_) | clean::ImplTrait(_)
| clean::Infer => None, | clean::Infer
| clean::UnsafeBinder(_) => None,
} }
} }

View file

@ -573,7 +573,7 @@ impl FromClean<clean::Type> for Type {
fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self { fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self {
use clean::Type::{ use clean::Type::{
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath, Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
RawPointer, SelfTy, Slice, Tuple, RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
}; };
match ty { match ty {
@ -613,6 +613,8 @@ impl FromClean<clean::Type> for Type {
self_type: Box::new(self_type.into_json(renderer)), self_type: Box::new(self_type.into_json(renderer)),
trait_: trait_.map(|trait_| trait_.into_json(renderer)), trait_: trait_.map(|trait_| trait_.into_json(renderer)),
}, },
// FIXME(unsafe_binder): Implement rustdoc-json.
UnsafeBinder(_) => todo!(),
} }
} }
} }

View file

@ -21,7 +21,7 @@
/// } /// }
/// ``` /// ```
/// ///
/// But this shoudln't produce a warning: /// But this shouldn't produce a warning:
/// ```rust,no_run /// ```rust,no_run
/// # extern crate pub_trait; /// # extern crate pub_trait;
/// # use pub_trait::Trait; /// # use pub_trait::Trait;

View file

@ -0,0 +1,4 @@
#![feature(unsafe_binders)]
#![allow(incomplete_features)]
pub fn woof() -> unsafe<'a> &'a str { todo!() }

View file

@ -0,0 +1,15 @@
//@ aux-build:unsafe-binder-dep.rs
#![feature(unsafe_binders)]
#![allow(incomplete_features)]
extern crate unsafe_binder_dep;
//@ has 'unsafe_binder/fn.woof.html' //pre "fn woof() -> unsafe<'a> &'a str"
pub use unsafe_binder_dep::woof;
//@ has 'unsafe_binder/fn.meow.html' //pre "fn meow() -> unsafe<'a> &'a str"
pub fn meow() -> unsafe<'a> &'a str { todo!() }
//@ has 'unsafe_binder/fn.meow_squared.html' //pre "fn meow_squared() -> unsafe<'b, 'a> &'a &'b str"
pub fn meow_squared() -> unsafe<'b, 'a> &'a &'b str { todo!() }

View file

@ -6,7 +6,7 @@ fn func(func_arg: &mut V) {
|| { || {
// Declaring `x` separately instead of using // Declaring `x` separately instead of using
// a destructuring binding like `let V(x) = ...` // a destructuring binding like `let V(x) = ...`
// becaue only `V(x) = ...` triggers the ICE // because only `V(x) = ...` triggers the ICE
let x; let x;
V(x) = func_arg; //~ ERROR: mismatched types V(x) = func_arg; //~ ERROR: mismatched types
func_arg.0 = 0; func_arg.0 = 0;

View file

@ -6,7 +6,7 @@
// to process this `'r` region bound. In particular, to be WF, the // to process this `'r` region bound. In particular, to be WF, the
// region bound must meet the requirements of the trait, and hence we // region bound must meet the requirements of the trait, and hence we
// got `for<'r> { 'r: 'static }`. This would ICE because the `Binder` // got `for<'r> { 'r: 'static }`. This would ICE because the `Binder`
// constructor we were using was assering that no higher-ranked // constructor we were using was asserting that no higher-ranked
// regions were involved (because the WF code is supposed to skip // regions were involved (because the WF code is supposed to skip
// those). The error (if debug-asserions were disabled) came because // those). The error (if debug-asserions were disabled) came because
// we obviously cannot prove that `'r: 'static` for any region `'r`. // we obviously cannot prove that `'r: 'static` for any region `'r`.

View file

@ -17,7 +17,7 @@
// `__rust_{begin,end}_short_backtrace` markers, which only appear in full // `__rust_{begin,end}_short_backtrace` markers, which only appear in full
// backtraces. The rest of the backtrace is filtered out. // backtraces. The rest of the backtrace is filtered out.
// //
// Ignored on msvc becaue the `__rust_{begin,end}_short_backtrace` symbols // Ignored on msvc because the `__rust_{begin,end}_short_backtrace` symbols
// aren't reliable. // aren't reliable.
fn main() { missing_ident; } fn main() { missing_ident; }