mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 16:14:50 +00:00
[cfe] Support current uri for crashes during top level inference
+ avoid printing the stack trace twice on crash Change-Id: Iac220117b77c30bc03212b2727efe88036819357 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260700 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Jens Johansen <jensj@google.com>
This commit is contained in:
parent
51114fca8a
commit
d43aa20afa
|
@ -10,6 +10,7 @@ import 'dart:io'
|
|||
show ContentType, HttpClient, HttpClientRequest, SocketException, stderr;
|
||||
|
||||
import 'problems.dart' show DebugAbort;
|
||||
import 'uri_offset.dart';
|
||||
|
||||
const String defaultServerAddress = "http://127.0.0.1:59410/";
|
||||
|
||||
|
@ -35,11 +36,20 @@ class Crash {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
return """
|
||||
Crash when compiling $uri,
|
||||
at character offset $charOffset:
|
||||
$error${trace == null ? '' : '\n$trace'}
|
||||
""";
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (uri != null) {
|
||||
sb.write("Crash when compiling $uri");
|
||||
if (charOffset != null && charOffset != -1) {
|
||||
sb.write(" at character offset $charOffset:\n");
|
||||
} else {
|
||||
sb.write(":\n");
|
||||
}
|
||||
} else {
|
||||
sb.write("Crash when compiling:\n");
|
||||
}
|
||||
sb.write(error);
|
||||
sb.write("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +126,7 @@ String safeToString(Object object) {
|
|||
}
|
||||
|
||||
Future<T> withCrashReporting<T>(
|
||||
Future<T> Function() action, Uri? Function() currentUri) async {
|
||||
Future<T> Function() action, UriOffset? Function() currentUriOffset) async {
|
||||
resetCrashReporting();
|
||||
try {
|
||||
return await action();
|
||||
|
@ -125,6 +135,7 @@ Future<T> withCrashReporting<T>(
|
|||
} on DebugAbort {
|
||||
rethrow;
|
||||
} catch (e, s) {
|
||||
return reportCrash(e, s, currentUri());
|
||||
UriOffset? uriOffset = currentUriOffset();
|
||||
return reportCrash(e, s, uriOffset?.uri, uriOffset?.fileOffset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,29 +315,31 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
|
|||
void inferFormalTypes(ClassHierarchyBase hierarchy) {
|
||||
if (_hasFormalsInferred) return;
|
||||
if (formals != null) {
|
||||
for (FormalParameterBuilder formal in formals!) {
|
||||
if (formal.type is InferableTypeBuilder) {
|
||||
if (formal.isInitializingFormal) {
|
||||
formal.finalizeInitializingFormal(classBuilder, hierarchy);
|
||||
libraryBuilder.loader.withUriForCrashReporting(fileUri, charOffset, () {
|
||||
for (FormalParameterBuilder formal in formals!) {
|
||||
if (formal.type is InferableTypeBuilder) {
|
||||
if (formal.isInitializingFormal) {
|
||||
formal.finalizeInitializingFormal(classBuilder, hierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_hasSuperInitializingFormals) {
|
||||
List<Initializer>? initializers;
|
||||
if (beginInitializers != null) {
|
||||
BodyBuilder bodyBuilder = libraryBuilder.loader
|
||||
.createBodyBuilderForOutlineExpression(libraryBuilder,
|
||||
classBuilder, this, classBuilder.scope, fileUri);
|
||||
if (isConst) {
|
||||
bodyBuilder.constantContext = ConstantContext.required;
|
||||
if (_hasSuperInitializingFormals) {
|
||||
List<Initializer>? initializers;
|
||||
if (beginInitializers != null) {
|
||||
BodyBuilder bodyBuilder = libraryBuilder.loader
|
||||
.createBodyBuilderForOutlineExpression(libraryBuilder,
|
||||
classBuilder, this, classBuilder.scope, fileUri);
|
||||
if (isConst) {
|
||||
bodyBuilder.constantContext = ConstantContext.required;
|
||||
}
|
||||
initializers = bodyBuilder.parseInitializers(beginInitializers!,
|
||||
doFinishConstructor: false);
|
||||
}
|
||||
initializers = bodyBuilder.parseInitializers(beginInitializers!,
|
||||
doFinishConstructor: false);
|
||||
finalizeSuperInitializingFormals(
|
||||
hierarchy, _superParameterDefaultValueCloners, initializers);
|
||||
}
|
||||
finalizeSuperInitializingFormals(
|
||||
hierarchy, _superParameterDefaultValueCloners, initializers);
|
||||
}
|
||||
});
|
||||
}
|
||||
_hasFormalsInferred = true;
|
||||
}
|
||||
|
|
|
@ -481,35 +481,38 @@ class SourceFieldBuilder extends SourceMemberBuilderImpl
|
|||
return fieldType;
|
||||
}
|
||||
|
||||
InferredType implicitFieldType = fieldType as InferredType;
|
||||
DartType inferredType = implicitFieldType.computeType(hierarchy);
|
||||
if (fieldType is InferredType) {
|
||||
// `fieldType` may have changed if a circularity was detected when
|
||||
// [inferredType] was computed.
|
||||
if (!libraryBuilder.isNonNullableByDefault) {
|
||||
inferredType = legacyErasure(inferredType);
|
||||
}
|
||||
type.registerInferredType(inferredType);
|
||||
return libraryBuilder.loader.withUriForCrashReporting(fileUri, charOffset,
|
||||
() {
|
||||
InferredType implicitFieldType = fieldType as InferredType;
|
||||
DartType inferredType = implicitFieldType.computeType(hierarchy);
|
||||
if (fieldType is InferredType) {
|
||||
// `fieldType` may have changed if a circularity was detected when
|
||||
// [inferredType] was computed.
|
||||
if (!libraryBuilder.isNonNullableByDefault) {
|
||||
inferredType = legacyErasure(inferredType);
|
||||
}
|
||||
type.registerInferredType(inferredType);
|
||||
|
||||
IncludesTypeParametersNonCovariantly? needsCheckVisitor;
|
||||
if (parent is ClassBuilder) {
|
||||
Class enclosingClass = classBuilder!.cls;
|
||||
if (enclosingClass.typeParameters.isNotEmpty) {
|
||||
needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
|
||||
enclosingClass.typeParameters,
|
||||
// We are checking the field type as if it is the type of the
|
||||
// parameter of the implicit setter and this is a contravariant
|
||||
// position.
|
||||
initialVariance: Variance.contravariant);
|
||||
IncludesTypeParametersNonCovariantly? needsCheckVisitor;
|
||||
if (parent is ClassBuilder) {
|
||||
Class enclosingClass = classBuilder!.cls;
|
||||
if (enclosingClass.typeParameters.isNotEmpty) {
|
||||
needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
|
||||
enclosingClass.typeParameters,
|
||||
// We are checking the field type as if it is the type of the
|
||||
// parameter of the implicit setter and this is a contravariant
|
||||
// position.
|
||||
initialVariance: Variance.contravariant);
|
||||
}
|
||||
}
|
||||
if (needsCheckVisitor != null) {
|
||||
if (fieldType.accept(needsCheckVisitor)) {
|
||||
_fieldEncoding.setGenericCovariantImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needsCheckVisitor != null) {
|
||||
if (fieldType.accept(needsCheckVisitor)) {
|
||||
_fieldEncoding.setGenericCovariantImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
return fieldType;
|
||||
return fieldType;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -86,6 +86,7 @@ import '../scope.dart';
|
|||
import '../ticker.dart' show Ticker;
|
||||
import '../type_inference/type_inference_engine.dart';
|
||||
import '../type_inference/type_inferrer.dart';
|
||||
import '../uri_offset.dart';
|
||||
import '../util/helpers.dart';
|
||||
import '../uris.dart';
|
||||
import 'diet_listener.dart' show DietListener;
|
||||
|
@ -229,7 +230,7 @@ class SourceLoader extends Loader {
|
|||
|
||||
int byteCount = 0;
|
||||
|
||||
Uri? currentUriForCrashReporting;
|
||||
UriOffset? currentUriForCrashReporting;
|
||||
|
||||
ClassBuilder? _macroClassBuilder;
|
||||
|
||||
|
@ -287,6 +288,16 @@ class SourceLoader extends Loader {
|
|||
_builders.clear();
|
||||
}
|
||||
|
||||
/// Run [f] with [uri] and [fileOffset] as the current uri/offset used for
|
||||
/// reporting crashes.
|
||||
T withUriForCrashReporting<T>(Uri uri, int fileOffset, T Function() f) {
|
||||
UriOffset? oldUriForCrashReporting = currentUriForCrashReporting;
|
||||
currentUriForCrashReporting = new UriOffset(uri, fileOffset);
|
||||
T result = f();
|
||||
currentUriForCrashReporting = oldUriForCrashReporting;
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
LibraryBuilder get coreLibrary => _coreLibrary!;
|
||||
|
||||
|
@ -659,7 +670,8 @@ class SourceLoader extends Loader {
|
|||
Future<Null> buildBodies(List<SourceLibraryBuilder> libraryBuilders) async {
|
||||
assert(_coreLibrary != null);
|
||||
for (SourceLibraryBuilder library in libraryBuilders) {
|
||||
currentUriForCrashReporting = library.importUri;
|
||||
currentUriForCrashReporting =
|
||||
new UriOffset(library.importUri, TreeNode.noOffset);
|
||||
await buildBody(library);
|
||||
}
|
||||
// Workaround: This will return right away but avoid a "semi leak"
|
||||
|
@ -1006,7 +1018,8 @@ severity: $severity
|
|||
_ensureCoreLibrary();
|
||||
while (_unparsedLibraries.isNotEmpty) {
|
||||
SourceLibraryBuilder library = _unparsedLibraries.removeFirst();
|
||||
currentUriForCrashReporting = library.importUri;
|
||||
currentUriForCrashReporting =
|
||||
new UriOffset(library.importUri, TreeNode.noOffset);
|
||||
await buildOutline(library);
|
||||
}
|
||||
currentUriForCrashReporting = null;
|
||||
|
|
|
@ -35,6 +35,7 @@ import '../kernel/late_lowering.dart' as late_lowering;
|
|||
import '../names.dart';
|
||||
import '../problems.dart' show unhandled;
|
||||
import '../source/source_library_builder.dart';
|
||||
import '../uri_offset.dart';
|
||||
import 'closure_context.dart';
|
||||
import 'for_in.dart';
|
||||
import 'inference_helper.dart';
|
||||
|
@ -233,7 +234,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
|
||||
/// Computes uri and offset for [node] for internal errors in a way that is
|
||||
/// safe for both top-level and full inference.
|
||||
_UriOffset _computeUriOffset(TreeNode node) {
|
||||
UriOffset _computeUriOffset(TreeNode node) {
|
||||
Uri uri;
|
||||
int fileOffset;
|
||||
if (!isTopLevel) {
|
||||
|
@ -252,12 +253,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
fileOffset = TreeNode.noOffset;
|
||||
}
|
||||
}
|
||||
return new _UriOffset(uri, fileOffset);
|
||||
return new UriOffset(uri, fileOffset);
|
||||
}
|
||||
|
||||
ExpressionInferenceResult _unhandledExpression(
|
||||
Expression node, DartType typeContext) {
|
||||
_UriOffset uriOffset = _computeUriOffset(node);
|
||||
UriOffset uriOffset = _computeUriOffset(node);
|
||||
unhandled("${node.runtimeType}", "InferenceVisitor", uriOffset.fileOffset,
|
||||
uriOffset.uri);
|
||||
}
|
||||
|
@ -479,7 +480,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
}
|
||||
|
||||
StatementInferenceResult _unhandledStatement(Statement node) {
|
||||
_UriOffset uriOffset = _computeUriOffset(node);
|
||||
UriOffset uriOffset = _computeUriOffset(node);
|
||||
return unhandled("${node.runtimeType}", "InferenceVisitor",
|
||||
uriOffset.fileOffset, uriOffset.uri);
|
||||
}
|
||||
|
@ -1364,7 +1365,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
} else if (syntheticAssignment is InvalidExpression || hasProblem) {
|
||||
return new InvalidForInVariable(syntheticAssignment);
|
||||
} else {
|
||||
_UriOffset uriOffset = _computeUriOffset(syntheticAssignment!);
|
||||
UriOffset uriOffset = _computeUriOffset(syntheticAssignment!);
|
||||
return unhandled(
|
||||
"${syntheticAssignment.runtimeType}",
|
||||
"handleForInStatementWithoutVariable",
|
||||
|
@ -7455,13 +7456,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
}
|
||||
}
|
||||
|
||||
class _UriOffset {
|
||||
final Uri uri;
|
||||
final int fileOffset;
|
||||
|
||||
_UriOffset(this.uri, this.fileOffset);
|
||||
}
|
||||
|
||||
/// Offset and type information collection in [InferenceVisitor.inferMapEntry].
|
||||
class _MapLiteralEntryOffsets {
|
||||
// Stores the offset of the map entry found by inferMapEntry.
|
||||
|
|
10
pkg/front_end/lib/src/fasta/uri_offset.dart
Normal file
10
pkg/front_end/lib/src/fasta/uri_offset.dart
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
class UriOffset {
|
||||
final Uri uri;
|
||||
final int fileOffset;
|
||||
|
||||
UriOffset(this.uri, this.fileOffset);
|
||||
}
|
|
@ -32,6 +32,7 @@ import 'fasta/kernel/macro/macro.dart';
|
|||
import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
|
||||
import 'fasta/kernel/verifier.dart' show verifyComponent;
|
||||
import 'fasta/source/source_loader.dart' show SourceLoader;
|
||||
import 'fasta/uri_offset.dart';
|
||||
import 'fasta/uri_translator.dart' show UriTranslator;
|
||||
|
||||
/// Implementation for the
|
||||
|
@ -120,7 +121,10 @@ Future<CompilerResult> generateKernelInternal(
|
|||
includeHierarchyAndCoreTypes: includeHierarchyAndCoreTypes,
|
||||
retainDataForTesting: retainDataForTesting);
|
||||
}
|
||||
}, () => sourceLoader?.currentUriForCrashReporting ?? options.inputs.first);
|
||||
},
|
||||
() =>
|
||||
sourceLoader?.currentUriForCrashReporting ??
|
||||
new UriOffset(options.inputs.first, TreeNode.noOffset));
|
||||
}
|
||||
|
||||
Future<CompilerResult> _buildInternal(
|
||||
|
|
|
@ -312,7 +312,7 @@ class _AllFreeTypeVariablesVisitor implements DartTypeVisitor<void> {
|
|||
|
||||
@override
|
||||
bool defaultDartType(DartType node) {
|
||||
throw new UnsupportedError("Unsupported type $node (${node.runtimeType}.");
|
||||
throw new UnsupportedError("Unsupported type $node (${node.runtimeType}).");
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
Loading…
Reference in a new issue